核心是分阶段协同:每步用独立countdownlatch控制,线程池内并行执行,主线程await等待本阶段完成再启下阶段;共享状态需线程安全,线程池按阶段特征配置,并显式处理超时与异常。

用线程池配合 CountDownLatch 实现多线程多步调并行计算,核心在于:**分阶段控制执行节奏,让各线程在关键节点同步等待,同时避免阻塞主线程或浪费资源**。关键不是“一起开始、一起结束”,而是“分批启动、按步协同”。
明确每一步的并发粒度和依赖关系
多步调意味着计算流程存在逻辑上的阶段性,比如:第一步加载数据 → 第二步预处理 → 第三步模型推理 → 第四步结果聚合。每步内部可并行,但后一步必须等前一步全部完成才能开始。
- 把整个流程拆成若干 独立阶段(Phase),每个阶段对应一个
CountDownLatch实例(例如latch1控制阶段1结束,latch2控制阶段2结束) - 阶段之间通过
latch.await()阻塞当前线程(通常是主线程或协调线程),而非让工作线程空转 - 每个阶段内,提交任务到线程池,任务完成时调用
latch.countDown();所有任务完成,计数归零,下一阶段才被唤醒
用共享状态 + latch 控制跨阶段数据流转
阶段间需要传递中间结果(如阶段1输出一批对象,阶段2要消费它们)。不能靠全局变量硬耦合,推荐用线程安全容器封装状态,并配合 latch 确保读写时序。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 定义一个
AtomicReference<list>></list>或ConcurrentLinkedQueue存储阶段产出,阶段1任务写入,阶段2任务读取 - 阶段1所有任务提交后,主线程调用
latch1.await();待其返回,再启动阶段2任务(此时中间数据已就绪) - 避免在阶段1任务里直接触发阶段2——那会破坏步骤边界,也容易引发竞态
线程池配置需匹配阶段特征
不同阶段的计算密度、I/O占比、内存消耗差异大,统一用 FixedThreadPool 可能低效甚至拖垮。
- 纯 CPU 密集型阶段(如数值计算):线程数 ≈ CPU 核心数,用
Executors.newFixedThreadPool(n) - 含远程调用或文件读写阶段:适当增大线程数(如核数 × 2~3),或改用
newCachedThreadPool()(注意回收策略) - 务必为线程池设置有意义的
ThreadFactory(打日志/标阶段名),便于排查哪一阶段卡住
异常与超时必须显式处理
CountDownLatch.await() 可被中断,且不抛出 ExecutionException;任务异常若未捕获,会导致 latch 永不减到 0,主线程永久阻塞。
- 每个阶段任务内部包一层 try-catch,捕获异常后记录日志 + 调用
latch.countDown()(确保计数正常归零) -
await()务必带超时参数:if (!latch.await(30, TimeUnit.SECONDS)) { throw new TimeoutException("Phase X timeout"); } - 阶段失败时,考虑调用
executor.shutdownNow()中止后续阶段,防止资源泄漏
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










