CountDownLatch是Java中用于线程同步的“一次性倒计时门闩”,核心用途是主线程等待多个子任务完成、并行计算后汇总结果、或屏障式同步启动;不可重用,归零即失效,需根据场景选用CyclicBarrier或Semaphore替代。

CountDownLatch 是 Java 并发编程中协调线程执行顺序的核心工具,本质是一个“一次性倒计时门闩”。它不负责任务调度或资源共享,而是专注解决“等全部做完再继续”的同步需求。用对场景,代码简洁可靠;用错地方,反而引入阻塞或死等风险。
主线程等待多个子任务完成
这是最典型、最高频的使用方式。例如启动服务时需加载配置、连接数据库、初始化缓存等多个模块,每个模块由独立线程异步准备,主线程必须等全部就绪才对外提供服务。
- 创建 CountDownLatch 时,count 值设为子任务线程数(如 3 个初始化任务 → new CountDownLatch(3))
- 每个子线程执行完自身逻辑后,必须调用 latch.countDown() —— 建议放在 finally 块中,避免异常跳过导致计数卡住
- 主线程在所有子线程 start() 后,立即调用 latch.await() 阻塞等待
多线程并行处理 + 主线程汇总结果
适用于可拆分的计算型任务,比如批量查询用户信息、并行下载文件片段、分片数据统计等。各线程各自处理一部分,完成后通知,主线程统一收集与合并。
- 避免在 await() 前就提前访问未完成的结果容器(如 ArrayList),否则可能读到空或不全的数据
- 若需超时控制(防止某线程卡死拖垮整体),改用 latch.await(10, TimeUnit.SECONDS),返回 false 时应做降级或告警
- 结果汇总逻辑必须放在 await() 之后,确保所有 countDown() 已触发
模拟并发压测或屏障式启动
让多个线程“同时”开始执行,常用于性能测试、竞态条件复现或需要严格时间对齐的场景。
立即学习“Java免费学习笔记(深入)”;
- 初始化两个 CountDownLatch:一个作为“准备就绪”门闩(latchReady),一个作为“开始信号”门闩(latchGo)
- 每个工作线程先执行初始化,然后 latchReady.countDown();主线程 await() 等全部就绪后,再调用 latchGo.countDown()
- 所有工作线程在 latchReady.await() 后,统一等待 latchGo.await(),实现毫秒级同步启动
注意不可重用与替代选择
CountDownLatch 计数归零即失效,无法 reset。若需循环等待(如每轮都等 N 个线程完成),应选用 CyclicBarrier;若需限制并发数(如最多 5 个线程同时执行),则 Semaphore 更合适。
- 不要试图通过反射或 new 新实例来“复用”同一个 CountDownLatch 对象,会破坏语义一致性
- getCount() 可用于日志或监控,但不应作为业务分支判断依据(存在竞态,值可能瞬间变化)
- await() 可能被中断,务必捕获 InterruptedException 并合理处理(如恢复中断状态 Thread.currentThread().interrupt())

















