countdownlatch用于协调多线程等待所有任务完成,核心是阻塞等待而非结果收集;需配合线程安全容器(如concurrenthashmap)存储结果,且不可重用,计数归零后须改用cyclicbarrier或completablefuture。

CountDownLatch 是 Java 并发包中用于协调多个线程等待某组操作完成的同步工具。它不适用于任务结果的收集,但能精准控制“所有任务执行完毕后才继续”的流程,是实现多任务并行后统一汇总的常用基础组件。
CountDownLatch 的核心作用是“等待”,不是“传值”
CountDownLatch 本身不保存任务结果,也不参与计算逻辑。它的价值在于阻塞主线程(或某个协调线程),直到所有并行子任务调用 countDown() 将计数器减为 0。因此,你需要配合其他结构(如 List、Map、AtomicReference 等)来安全地收集各线程的执行结果。
- 初始化时指定计数值:new CountDownLatch(n),n 通常等于并行任务数量
- 每个子任务执行完自己的逻辑后,必须调用 latch.countDown() —— 即使发生异常也建议放在 finally 块中
- 主线程调用 latch.await() 阻塞等待,直到计数归零或超时
配合线程安全容器收集结果
多个线程同时写入结果时,需避免竞态条件。推荐使用以下方式之一:
- 使用 ConcurrentHashMap 或 CopyOnWriteArrayList 存储结果,适合无序汇总
- 用 AtomicInteger 或 AtomicLong 累加数值型结果(如统计总数、求和)
- 若需保持任务与结果顺序对应,可提前创建固定大小的 ArrayList,配合索引安全写入(例如用线程本地变量确定索引,或传递索引参数)
典型使用结构示例
以下是一个简洁可用的模式:
1. 创建 CountDownLatch(计数 = 任务数)和线程安全的结果容器
2. 启动 n 个线程(或提交到线程池),每个线程执行任务并把结果存入容器,最后调用 countDown()
3. 主线程 await() 等待全部完成,再从容器中读取结果进行汇总处理
注意:不要在子线程中直接修改共享的非线程安全对象(如普通 ArrayList),否则可能引发数据丢失或异常。
常见误区提醒
CountDownLatch 是一次性使用的 —— 计数归零后无法重置,再次 await() 会立即返回。如需重复使用,应考虑 CyclicBarrier;若还需结果聚合能力,可结合 CompletableFuture.allOf() + thenCombine/thenAccept 实现更函数式的汇总逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











