countdownlatch 是 java 并发包中基于计数器的同步工具,用于主线程等待指定数量子线程完成;需初始化时指定准确线程数,子线程须在 finally 中调用 countdown(),主线程调用 await() 阻塞等待,且不可重用。

CountDownLatch 是 Java 并发包(java.util.concurrent)中一个轻量级的同步工具,常用于“主线程等待一组子线程全部完成后再继续执行”的场景。它的核心是内部一个计数器,每次调用 countDown() 就减 1,主线程调用 await() 会阻塞,直到计数器归零或被中断。
初始化 CountDownLatch 并传入线程数量
创建时需指定“期待完成的子线程总数”。这个数字必须和实际启动的子线程数量严格一致,否则 await() 可能永远阻塞(计数器无法归零)或过早返回(计数器提前为 0)。
示例:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
子线程执行完任务后调用 countDown()
每个子线程在自身逻辑结束前(无论成功或异常),都应确保调用一次 latch.countDown()。推荐放在 finally 块中,避免因异常导致计数未减少。
- 不要在子线程中重复调用
countDown()(除非有意多次触发) - 即使子线程抛出异常,也要保证
countDown()执行
示例:
new Thread(() -> {try {
// 模拟业务处理
} finally {
latch.countDown(); // 保证执行
}
}).start();
主线程调用 await() 阻塞等待
主线程在启动所有子线程后,立即调用 latch.await()。该方法会挂起当前线程,直到计数器变为 0 或当前线程被中断。
可选带超时的版本:latch.await(10, TimeUnit.SECONDS),避免无限等待;若超时返回 false,需自行判断是否继续或报错。
注意:CountDownLatch 不可重用
一旦计数器归零,await() 将不再阻塞,且后续无法重置计数器。如果需要循环等待(如多轮任务),应每次新建 CountDownLatch 实例,或改用 CyclicBarrier。
常见误用:
- 漏掉某个子线程的
countDown() - 主线程在子线程启动前就调用了
await() - 误以为
await()能捕获子线程异常(它不能;异常需通过其他方式传递,如Future或共享变量)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










