countdownlatch是基于aqs共享模式的一次性同步工具,通过state计数器实现线程等待:构造时指定正整数n,countdown()递减计数,await()阻塞直至归零后唤醒所有等待线程,不可重置、不控制临界资源。

CountDownLatch 是 Java 并发编程中轻量、直观且高频使用的同步协作工具,核心作用是让一个或多个线程“等待”其他若干线程完成任务后再继续执行。它不控制临界资源访问,也不替代锁,而是解决“阶段同步”问题——比如初始化完毕再启动服务、所有子任务跑完再汇总结果。
CountDownLatch 的本质与关键特性
它内部封装了一个基于 AQS(AbstractQueuedSynchronizer)的共享模式同步器,计数器值即 AQS 的 state 字段。构造时指定正整数 count,之后只能递减(countDown()),不能重置、不能增加。一旦归零,所有阻塞在 await() 上的线程被唤醒,且后续调用 await() 会立即返回——它是一次性、不可重用的。
- 若构造时传入 0,
await()不阻塞,直接通过 - 计数器为负数非法,构造会抛
IllegalArgumentException -
getCount()仅适合调试或监控,不应作为业务逻辑判断依据
标准用法:三步闭环
典型使用围绕三个动作展开,缺一不可:
-
创建:主线程(或协调者)初始化
CountDownLatch latch = new CountDownLatch(N),N 是需等待的子任务/线程数量 -
等待:主线程调用
latch.await()(可选带超时版本),进入阻塞状态 -
递减:每个子线程完成自身工作后,必须调用一次
latch.countDown();无论成功或异常,建议放在finally块中确保执行
注意:countDown() 可由任意线程调用,不局限于创建它的线程;多次调用只影响计数器数值,不会报错。
实用技巧与避坑指南
实际编码中容易忽略但影响稳定性的细节:
-
超时保护必加:生产环境避免无限等待,优先用
await(long timeout, TimeUnit unit),返回false时表示超时,应做失败处理(如日志、清理、降级) -
异常不中断计数:子线程抛出异常未捕获,会导致
countDown()被跳过,计数器无法归零——务必包裹在try-finally或catch后显式调用 -
避免反向依赖:不要在调用
countDown()前等待同一个 CountDownLatch,否则可能造成死锁或逻辑卡死 -
区分 CyclicBarrier:需要重复使用的场景(如多轮批处理),应换用
CyclicBarrier,而非反复新建 CountDownLatch
典型适用场景举例
它最适合“单次汇聚型”协作,常见于:
- 服务启动协调:多个模块(配置加载、缓存预热、连接池初始化)并行启动,主服务等待全部就绪后才对外提供请求
- 批量任务合并:将大文件拆分下载/处理,各线程独立完成分片后,主线程统一合并输出
- 测试环境模拟:JUnit 中启动多个异步操作,验证它们是否在规定时间内全部完成
- 性能压测同步点:让 N 个线程同时开始执行,用 CountDownLatch 控制“起跑线”
不复杂但容易忽略——用对时机,它就是并发协作中最稳的一根“同步绳”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











