cyclicbarrier 的核心优势在于自动重置实现重用,需固定线程数与明确阶段边界;每轮全员调用 await() 后触发回调,异常或中断会导致破损,需捕获 brokenbarrierexception 并合理调用 reset() 恢复。

CyclicBarrier 的重用能力是它区别于 CountDownLatch 的核心优势,关键在于“自动重置”——每轮所有线程到达后,屏障内部状态会清零并进入下一轮等待,无需手动重建对象。
重用的前提:固定线程组 + 明确阶段边界
重用不是无条件的,它依赖两个基础条件:参与协同的线程数量(parties)必须固定;任务需天然划分为多个逻辑阶段,每个阶段结束即是一次同步点。比如批量处理10万条数据,每1000条为一轮,每轮由5个线程并行计算,完成后统一汇总再进下一轮——这种结构天然适配 CyclicBarrier 重用。
- 线程数在初始化时定死,后续不能增减;若某轮有线程异常退出,屏障会破损(broken),需调用 reset() 恢复或重新创建
- 每个阶段内,所有线程都必须调用一次 await();少一次,整组线程就会永久阻塞
- 重用发生在同一 CyclicBarrier 实例上,不是靠循环里 new 新对象实现的
构造时指定回调,让最后一人做收尾动作
带 Runnable 参数的构造方式能自然支撑多轮协调:回调只在每轮全员到齐时执行一次,且由最后一个到达的线程同步运行,不另起线程。适合记录日志、更新共享计数器、切换全局标志位等轻量操作。
- 回调中避免耗时操作,否则会拖慢整组线程的释放速度
- 回调抛出异常会导致屏障破损,其他线程收到 BrokenBarrierException
- 例如:每轮结束后打印“第X轮完成”,或把本轮结果存入 ConcurrentHashMap 的特定 key 下
异常处理与破损恢复是重用稳定性的关键
重用过程中最常见风险是 BrokenBarrierException ——只要任一 await() 调用被中断、超时或屏障被 reset(),当前轮就失败,屏障进入破损状态。此时所有等待线程都会收到该异常,后续 await() 也会立即抛出。
- 使用 try-catch 捕获 BrokenBarrierException 和 InterruptedException,并根据业务决定是否重试或终止
- 调用 barrier.isBroken() 可判断当前状态;调用 barrier.reset() 可强行恢复屏障(即使还有线程在等待),但要确保调用时机安全
- 建议搭配超时版 await(long timeout, TimeUnit unit),防止因个别线程卡死导致整组无限挂起
典型重用代码结构:两轮以上才见真章
单轮调用看不出重用价值。真正体现设计意图的是循环中多次 await(),且每次都能成功触发回调并继续下一轮。
- 每个工作线程的 run 方法里,用 for 或 while 循环包裹 await() 调用
- 主线程或调度逻辑控制总轮数,子线程各自推进阶段进度
- 示例片段:一个线程执行 phase=0 → await() → phase=1 → await() → 结束,屏障在两轮中各生效一次
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











