假设现在有A任务和B任务,而B任务需要A任务的计算结果,因此需要A任务执行完毕才能执行B任务。现在假设A任务是一个十分耗时的任务,因此我们需要开启10线程同时运行以减少运行时间,那么如何判断A任务的10个线程已经执行完毕了呢?我们可以用CountDownLatch来解决这个问题,代码如下:
@Slf4j
public class CountDownLatchExample1 {
private final static int threadCount = 10;
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
final int threadNum = i;
executorService.execute(() -> {
try {
test(threadNum);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
});
}
try {
log.info("等待A任务执行完毕....");
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("A任务执行完毕,开始执行B任务");
executorService.shutdown();
}
private static void test(int threadNum) throws InterruptedException {
Thread.sleep(100);
log.info("正在执行A任务-{}", threadNum);
Thread.sleep(100);
}
}
运行结果如下:
12:52:13.430 [main] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 等待A任务执行完毕....
12:52:13.529 [pool-1-thread-2] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-1
12:52:13.530 [pool-1-thread-10] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-9
12:52:13.529 [pool-1-thread-1] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-0
12:52:13.529 [pool-1-thread-7] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-6
12:52:13.530 [pool-1-thread-9] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-8
12:52:13.529 [pool-1-thread-6] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-5
12:52:13.529 [pool-1-thread-4] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-3
12:52:13.529 [pool-1-thread-3] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-2
12:52:13.529 [pool-1-thread-5] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-4
12:52:13.529 [pool-1-thread-8] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - 正在执行A任务-7
12:52:13.630 [main] INFO com.lzc.concurrency.example.aqs.CountDownLatchExample1 - A任务执行完毕,开始执行B任务
Process finished with exit code 0
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。对于给定的计数 初始化 CountDownLatch,可以调用了 countDown() 方法,在当前计数到达零之前,await() 方法会一直受阻塞,当计数到达零时,会释放所有等待的线程,await() 的所有后续调用都将立即返回。但这种现象只出现一次——计数无法被重置,如果需要重置计数,请考虑使用 CyclicBarrier。
CountDownLatch 是一个通用同步工具,它有很多用途,将计数 初始化为1的 CountDownLatch可 用作一个简单的开/关锁存器或入口,在通过调用 countDown() 的线程打开入口前,所有调用 await() 的线程都一直在入口处等待。用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。