countdownlatch 是一次性倒计时门闩,用于主线程等待多个子任务完成:初始化指定计数,子任务调用 countdown() 减一,主线程 await() 阻塞至归零;需在 finally 中调用 countdown(),不可重用,适合无返回值的“一主多从”场景。

CountDownLatch 是 Java 并发编程中轻量、易用的同步辅助类,特别适合“等待多个子任务完成后再执行主逻辑”的场景,比如任务分发后的结果汇总、批量处理的协调启动等。
核心机制:一个倒计数的门闩
CountDownLatch 内部维护一个整型计数器,初始化时指定次数(如 new CountDownLatch(5) 表示需等待 5 次 signal)。调用 countDown() 使计数减一;调用 await() 的线程会阻塞,直到计数归零或被中断。一旦归零,所有 await 线程被唤醒,且后续 await 调用将立即返回——它不可重用,只是一次性门闩。
任务分发中的典型用法
当主线程派发多个异步子任务(如并发调用多个微服务、并行处理数据分片),需要确保全部完成才继续后续操作(如聚合结果、更新状态),CountDownLatch 就是简洁可靠的选择:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 主线程创建 CountDownLatch,计数值 = 子任务数量
- 每个子任务在线程池中执行,完成后调用 latch.countDown()
- 主线程在分发完所有任务后调用 latch.await(),阻塞等待全部完成
- 可设置超时(await(long timeout, TimeUnit unit))避免无限等待,超时后可做降级或重试处理
注意事项与常见陷阱
实际使用中需注意几个关键点,否则容易引发阻塞、漏通知或误判完成:
- countDown() 必须在每个子任务的 finally 块中调用,防止因异常未执行导致计数无法归零
- 不要在子任务中重复调用 countDown(),否则可能提前触发 await 返回,造成逻辑错乱
- await() 返回 false(超时)不等于失败,需结合业务判断是否重试、熔断或记录告警
- 若子任务本身也依赖其他同步机制(如锁、数据库事务),应确保 countDown 不在锁内或事务未提交前执行,避免死锁或状态不一致
替代方案对比:何时选 CountDownLatch?
类似需求下,也可考虑 CompletableFuture.allOf() 或 CyclicBarrier,但适用场景不同:
- CompletableFuture 更适合有返回值、需链式编排或异常传播的异步流程
- CyclicBarrier 支持重复使用,适合多轮协作(如迭代计算),且所有参与者都需显式 await
- CountDownLatch 最适合“一主多从”结构:一个线程等待多个独立任务结束,无返回值依赖,语义清晰、开销低
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










