CountDownLatch仅用于等待线程完成,不负责分段并行与结果汇总;需配合任务拆分、多线程执行、线程安全共享容器(如AtomicInteger、ConcurrentHashMap)及主线程汇总实现完整逻辑。

CountDownLatch 本身不负责“分段并行执行”或“汇总结果”,它只是一个同步辅助类,用于等待一组线程完成。真正实现分段并行 + 汇总,需要结合 任务拆分、多线程并发执行 和 共享结果容器(如 List、AtomicInteger、ConcurrentHashMap 等),再用 CountDownLatch 控制主线程等待。
一、明确分工:谁拆任务、谁执行、谁汇总
典型结构如下:
- 主线程:把大任务拆成 N 个子任务(例如按数组索引分片、按文件块切分);创建共享结果容器;启动 N 个工作线程;用 CountDownLatch.await() 阻塞等待全部完成。
- 每个工作线程:处理分配给自己的那部分数据;计算局部结果;将结果安全地写入共享容器(注意线程安全);调用 countDown() 告知完成。
- 主线程恢复后:统一读取共享容器,做最终汇总(如求和、合并列表、取最大值等)。
二、关键细节:如何安全汇总结果
避免竞态条件,不同场景推荐不同方式:
-
简单数值累加:用
AtomicInteger或AtomicLong,每个线程调用addAndGet()或incrementAndGet()。 -
收集多个对象(如 List
) :用CopyOnWriteArrayList(读多写少)或ConcurrentLinkedQueue(高并发插入),避免直接用 ArrayList 加 synchronized。 -
需要键值聚合(如统计词频):用
ConcurrentHashMap,配合merge()或computeIfAbsent()安全更新。 - 复杂对象或需定制逻辑:可为每个线程分配独立的局部结果对象(如自定义 Result 类),存入线程安全的集合,最后由主线程遍历合并。
三、一个完整示例:并行计算数组各段和,再汇总总和
假设对 int[] arr 执行 4 段并行求和:
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
int nThreads = 4;
CountDownLatch latch = new CountDownLatch(nThreads);
AtomicInteger totalSum = new AtomicInteger(0); // 共享结果
<p>int segmentSize = (arr.length + nThreads - 1) / nThreads;</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill9040" title="JavaStoryDevelop"><img
src="https://img.php.cn/upload/skill/000/000/081/179238966962420.jpg" alt="JavaStoryDevelop" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill9040" title="JavaStoryDevelop" class="overflowclass">JavaStoryDevelop</a>
<p class="overflowclass">你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在</p>
</div>
<a rel="nofollow" href="/xiazai/skill9040" title="JavaStoryDevelop" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><p>for (int i = 0; i </p><pre class="brush:php;toolbar:false;">new Thread(() -> {
int localSum = 0;
for (int j = start; j <p>}</p><p>try {
latch.await(); // 主线程等待全部完成
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("总和:" + totalSum.get()); // 输出 36
</p>四、替代方案提醒:更现代的写法
虽然 CountDownLatch 可用,但 Java 8+ 更推荐:
-
CompletableFuture:支持异步编排、异常处理、组合回调,天然适合分段并行 + 汇总。例如用
supplyAsync提交子任务,再用allOf+join()收集结果。 -
ForkJoinPool / parallelStream:对数组/集合做 map-reduce 风格计算时更简洁(如
Arrays.stream(arr).parallel().sum())。 - CountDownLatch 更适合“等待已知数量的异步操作结束”,而非主动管理结果结构。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










