CountDownLatch、CyclicBarrier、Semaphore
1. CountDownLatch
private static final int taskNum = 6;
public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CountDownLatch countDownLatch = new CountDownLatch(taskNum);
for (int i = 1; i <= taskNum; i++) {
final int idx = i;
threadPool.execute(() -> {
try {
System.out.println("当前正在处理任务: " + idx);
} catch (Exception e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
});
}
countDownLatch.await();
System.out.println("所有的任务都执行完毕!");
threadPool.shutdown();
}
2. CyclicBarrier
CyclicBarrier 和 CountDownLatch 非常类似,它也可以实现线程间的技术等待,但是它的功能比 CountDownLatch 更加复杂和强大。主要应用场景和 CountDownLatch 类似。CyclicBarrier 的字面意思是可循环使用(Cyclic )的屏障(Barrier )。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier 默认的构造方法是 CyclicBarrier(int parties) ,其参数表示屏障拦截的线程数量,每个线程调用 await() 方法告诉 CyclicBarrier 我已经到达了屏障,然后当前线程被阻塞。- 可以重复使用
private static final int taskNum = 6;
public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CyclicBarrier cyclicBarrier = new CyclicBarrier(taskNum, () -> {
System.out.println("所有人都到齐了,可以开始了");
});
for (int i = 1; i <= taskNum; i++) {
final int num = i;
threadPool.execute(() -> {
try {
System.out.println( num + " 号运行员已经准备好了.......");
}catch (Exception e){
e.printStackTrace();
}
try {
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
}
threadPool.shutdown();
}
3. Semaphore
- 允许多个线程同时访问:
synchronized 和 ReentrantLock 都是一次只允许一个线程访问某个资源,Semaphore (信号量)可以指定多个线程同时访问某个资源。 - 信号量主要用于两个目的:一个是用于多个共享资源的互斥使用,另一个用于并发线程数控制。
private static final int taskNum = 6;
public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= taskNum; i++) {
final int num = i;
threadPool.execute(() -> {
try {
semaphore.acquire();
System.out.println(num + " 号车获取到停车位.......");
TimeUnit.SECONDS.sleep(new Random().nextInt(3));
System.out.println(num + " 号车已经离开了停车位------");
} catch (Exception e) {
e.printStackTrace();
} finally {
semaphore.release();
}
});
}
threadPool.shutdown();
}
|