countdownlatch 是 java 并发包中用于线程等待协同的轻量级同步工具,通过递减计数器实现“一等多”协调,计数为 0 时唤醒所有 await 线程,不可重用,适用于一次性任务完成通知场景。

CountDownLatch 是 Java 并发包(java.util.concurrent)中用于线程间**等待协同**的轻量级同步工具,核心作用是:让一个或多个线程**等待其他线程完成一组操作后,再继续执行**。它不涉及锁竞争,也不可重用,适合“一次性”协调场景。
一、CountDownLatch 的基本原理
它内部维护一个整型计数器(count),初始化时指定初始值。每次调用 countDown() 方法,计数器减 1;当计数器变为 0 时,所有因调用 await() 而阻塞的线程被唤醒,继续执行。
关键特性:
- 计数器只能递减,不能重置(不可重用)
-
await()可响应中断,支持超时等待 - 不是锁,不关联任何“持有者”,纯信号机制
二、典型使用模式:主线程等待多个子任务完成
常见于“分治执行 + 汇总结果”场景,例如:启动 3 个线程并发下载文件,主线程等全部下载完再合并处理。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
示例代码结构:
(省略 import 和异常处理,聚焦逻辑)
CountDownLatch latch = new CountDownLatch(3); // 等待 3 个任务
// 启动 3 个子线程
for (int i = 0; i {
try {
// 执行耗时操作(如网络请求、计算)
doWork();
} finally {
latch.countDown(); // 完成后倒计时减 1
}
}).start();
}
// 主线程等待所有子线程完成
latch.await(); // 阻塞直到 count == 0
System.out.println("所有任务已完成,开始汇总...");
三、实用技巧与注意事项
实际使用中需注意几个关键点:
-
确保 countDown() 总被执行:建议放在
finally块中,避免因异常导致计数器卡住,使 await() 永久阻塞 -
await() 支持超时控制:用
latch.await(10, TimeUnit.SECONDS)避免无限等待,超时后可做降级或重试 -
不要和线程生命周期强绑定:CountDownLatch 关注的是“事件完成”,不是“线程结束”。即使某线程提前退出,只要它调用了
countDown(),就算一次有效通知 -
替代方案对比:若需重复使用,考虑
CyclicBarrier;若需更精细的线程协作(如阶段同步),可结合Phaser
四、进阶用法:多阶段协同(组合使用)
单个 CountDownLatch 适用于“一等多”模型。若需“多等多”或分阶段等待(如:先等全部启动,再等全部完成),可组合多个 CountDownLatch:
- 用
startLatch控制并发启动(所有线程await()后同时开始执行) - 用
finishLatch控制统一收尾(所有线程countDown()后主线程继续)
这种双栅栏模式能实现精确的并行节奏控制,常用于性能压测或模拟批量作业流水线。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










