CountDownLatch 用于主线程等待多个子线程完成后再执行,初始化时设为子线程数,子线程末尾调用 countDown()(推荐 try-finally),主线程调用 await() 阻塞等待,计数归零后继续执行,不可重用。

CountDownLatch 是 Java 并发包中用于线程同步的工具类,适合“一个线程等待多个子线程完成后再继续执行”的场景。它不是“倒计时器”本身,而是通过内部计数器实现“等待所有任务结束”的同步语义。所谓“同步倒计时”,本质是:主线程调用 await() 阻塞,子线程各自完成任务后调用 countDown() 减一,当计数归零,主线程被唤醒——这正是你想要的“多子线程协作完成、主线程统一收尾”的效果。
初始化 CountDownLatch,数量等于子线程数
在主线程中,根据你要并发启动的子线程数量(比如 5 个 HTTP 请求、5 个文件处理任务),创建对应初始值的 CountDownLatch:
int taskCount = 5; CountDownLatch latch = new CountDownLatch(taskCount);
这个 latch 就是主线程和所有子线程共享的“同步点”。注意:它不可重用,一次 await + countDown 组合后即失效。
子线程执行完任务后必须调用 countDown()
每个子线程在自己逻辑的**最后一步**(无论成功或失败)都要调用 latch.countDown()。这是关键,漏掉会导致主线程永远阻塞。
- 推荐包裹在
finally块中,确保异常也不遗漏 - 不需要关心谁先谁后,只要总共调用次数等于初始值,主线程就会被唤醒
new Thread(() -> {
try {
// 执行具体任务:查库、IO、计算等
doSomeWork();
} finally {
latch.countDown(); // ✅ 必须放这里
}
}).start();
主线程调用 await() 等待全部完成
主线程在启动所有子线程后,立即调用 latch.await()。该方法会阻塞,直到计数变为 0 或被中断:
- 可指定超时时间,避免无限等待:
latch.await(10, TimeUnit.SECONDS) - 返回
true表示计数归零成功;false表示超时;抛InterruptedException表示被中断 - await 返回后,即可安全执行汇总逻辑(如合并结果、更新 UI、记录日志)
// 启动全部子线程后
latch.await(); // 或带超时的版本
System.out.println("✅ 所有子任务已完成,开始汇总...");
常见误区与建议
- 不要在子线程里重复调用 await():那是主线程的事,子线程只负责 countDown
-
避免在主线程中提前 await:必须等所有子线程
start()之后再调用,否则可能子线程还没开始就已唤醒 -
不适用于“动态增减任务数”:CountDownLatch 初始化后计数值固定,如需动态管理,考虑
CyclicBarrier或CompletableFuture - 异常处理要到位:子线程内未捕获的异常不会自动触发 countDown,务必用 try-finally 保障

















