countdownlatch仅协调线程等待与释放,不负责结果汇总;需配合共享容器、原子变量或completablefuture等机制实现并行计算与结果汇总,且须注意一次性使用、异常安全及可见性保障。

CountDownLatch 本身不负责汇总结果,它只负责协调线程的等待与释放。真正实现并行计算+结果汇总,需要配合其他机制(如共享容器、原子变量或 Future)来收集各线程的计算结果,而 CountDownLatch 仅确保所有并行任务完成后再执行汇总逻辑。
用 List + synchronized 收集中间结果
适合结果类型统一、数量不多、对性能要求不高的场景。主线程提前创建线程安全的容器(如 ArrayList 配合同步块),每个工作线程计算完后将结果存入,并调用 countDown();主线程 await() 等待全部完成,再遍历汇总。
- 定义一个 volatile List
或普通 ArrayList,搭配 synchronized(this) 块写入,避免并发修改异常 - 每个子线程执行计算后,先写入结果,再 latch.countDown()
- 主线程调用 latch.await() 返回后,直接遍历 list 求和、取最大值等
用 AtomicInteger 或 AtomicReference 累加关键值
当只需汇总单一数值(如总和、计数、最大值)时,比集合更轻量。用原子类避免锁,配合 CountDownLatch 保证“所有更新已完成”这一时机。
- AtomicInteger sum = new AtomicInteger(0),每个线程算完调用 sum.addAndGet(localResult)
- 若需汇总对象(如统计信息),可用 AtomicReference
,配合 compareAndSet 实现无锁合并 - 注意:原子类适合可交换、可结合的操作(如 +、max、min),不适用于必须按顺序合并的逻辑
结合 CompletableFuture 实现异步+自动汇总
更现代的方式:用 CompletableFuture.allOf() 替代 CountDownLatch,天然支持链式汇总。每个任务返回 CompletableFuture,主线程用 thenCombine/thenApply 聚合结果,无需手动管理 latch。
- 启动多个 CompletableFuture.supplyAsync(() -> compute())
- 用 CompletableFuture.allOf(futures...).join() 等待全部完成
- 再调用 futures.stream().map(CompletableFuture::join).collect(...) 获取并汇总结果
- 优势是自带异常传播、组合能力,且无需显式 countDown
避免常见陷阱
CountDownLatch 是一次性门闩,重复使用需新建实例;同时要确保每个线程都执行 countDown(),否则 await() 会永久阻塞。
- 在 try-finally 块中调用 countDown(),防止异常跳过导致主线程卡死
- 不要在子线程中多次调用 countDown(),除非业务逻辑明确需要(比如分阶段完成)
- 汇总逻辑必须放在 await() 之后,不能依赖子线程写完就立刻读——仍需同步手段保障可见性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











