countdownlatch 是 java 中用于线程协作的轻量级同步工具,核心是让主线程等待多个子线程完成任务后再继续执行;需准确初始化计数值,配合 finally 中调用 countdown() 防异常阻塞,支持超时控制,且一次性使用不可重置。

CountDownLatch 是 Java 并发编程中轻量、直观且高频使用的同步工具,核心作用就一个:让一个线程(通常是主线程)等待多个其他线程完成任务后再继续执行。它不涉及锁竞争,也不要求共享变量加锁,靠的是“倒计时归零即放行”的简单逻辑。
初始化要匹配任务数量
构造 CountDownLatch 时传入的整数,代表你期望等待的“完成事件”总数。这个值必须准确对应实际要触发 countDown() 的次数,多一次或少一次都会导致 await() 永久阻塞或提前释放。
- 比如启动 5 个子线程处理数据,就 new CountDownLatch(5),不能写成 4 或 6
- 如果某个子线程因异常未执行 countDown(),计数器无法归零,await() 就会一直卡住——所以建议在 finally 块里调用 countDown()
- 计数器初始值为 0 是合法的:此时 await() 立即返回,适合做“无需等待”的占位或条件开关
await() 和 countDown() 要各司其职
await() 通常出现在协调者线程(如主线程)中,用于挂起自身;countDown() 则由每个工作线程在任务真正结束后调用,两者不可混淆。
- 不要在同一个线程里既调 await() 又调 countDown(),否则逻辑错乱
- countDown() 是无副作用的:调用多次也只减 1,但重复调用不会报错,只是可能掩盖漏调问题
- await() 支持超时控制:latch.await(3, TimeUnit.SECONDS) 可避免无限等待,返回 false 表示超时,程序可据此做降级或告警
典型场景离不开这三类用法
CountDownLatch 不是万能锁,但它在三类协作模式中几乎不可替代:
- 服务启动等待:Spring Boot 启动时,主线程等待数据库连接池、缓存客户端、配置加载等模块全部 ready 后才开放 HTTP 接口
- 并行任务汇总:把一批订单拆成 10 组并发查询,每组查完写入共享 List 并 countDown(),主线程 await() 后统一计算总金额
- 并发压测模拟:用一个 latch 控制所有线程“同时出发”,再用另一个 latch 等待全部结束,精准统计吞吐和延迟
用完即弃,别想重用
CountDownLatch 是一次性门闩。一旦计数器减到 0,所有 await() 都会立即返回,后续再调 await() 也不阻塞;同时 countDown() 继续调也没效果。它不是循环门,需要重复使用时请换 CyclicBarrier。
- 试图 reset 计数器会失败——API 没提供 reset 方法,强行反射修改 state 属于破坏设计契约
- 若业务需多次等待,常见做法是每次新建一个 CountDownLatch 实例,开销极小
- 注意别把它和 volatile boolean 标志位混用:后者无法保证“所有线程都看到 true” 的及时性,而 CountDownLatch 提供的是强顺序保证
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











