cyclicbarrier 是支持多线程“等齐再走”的可重用同步工具,需指定参与线程数 parties 和可选 barrieraction;await() 实现线程汇合,支持超时;具备自动重置、reset() 干预、isbroken() 检查等机制。

CyclicBarrier 是 Java 并发编程中用于多线程协同的关键工具,它的设计核心在于“等齐再走”——所有参与线程必须全部到达屏障点,才能集体继续执行。它不是单向等待,而是线程间相互等待;不依赖外部触发,而是由线程自身调用 await() 推动流程;更重要的是,它天然支持重复使用,适合多轮、分阶段的同步任务。
明确参与线程数与屏障动作
初始化 CyclicBarrier 时,必须指定 parties(参与线程总数)。这个数值一旦设定,就决定了每次同步所需的“到齐人数”。如果实际调用 await() 的线程少于该值,剩余线程将永久阻塞(除非超时或中断)。
可选的 barrierAction 是一个 Runnable,在所有线程到达后、唤醒前由最后一个到达的线程执行。它常用于:汇总中间结果、写日志、切换阶段状态、清理临时资源等。注意它不在独立线程中运行,而是复用当前线程上下文,避免额外调度开销。
- 若无需阶段动作,直接使用
new CyclicBarrier(4) - 若需聚合计算,可传入
new CyclicBarrier(4, this::mergeResults) - barrierAction 中抛出未捕获异常会导致屏障被破坏,后续 await 将立即抛出
BrokenBarrierException
合理使用 await() 控制线程汇合点
await() 是线程进入同步逻辑的入口。每次调用都会使内部计数器减 1,并将当前线程挂起,直到计数归零。它有两个重载版本:
-
await():无限等待,适用于确定所有线程都能正常抵达的场景 -
await(long timeout, TimeUnit unit):带超时机制,防止因某线程卡死、异常退出或网络延迟导致整个组阻塞
超时返回后,当前线程会抛出 TimeoutException,同时屏障被标记为“已破坏”,其他等待线程也会收到 BrokenBarrierException。这要求业务代码必须捕获并处理这两种异常,不能简单忽略。
利用可重用性支撑多阶段协作
CyclicBarrier 最大优势是自动重置:当所有线程通过一次屏障后,内部计数器恢复为初始 parties 值,可立刻用于下一轮同步。这种特性让它天然适配“分阶段并行处理”模式,比如:
- 第一阶段:3 个线程并行加载数据 → 到达 barrier 后合并结构
- 第二阶段:同一组线程并行转换格式 → 再次 await 等待齐备
- 第三阶段:并行写入或校验 → 继续复用同一个 barrier 实例
相比为每阶段新建 CountDownLatch,CyclicBarrier 减少了对象创建和 GC 压力,也更贴近“协作流”的语义表达。
主动干预与异常防护机制
虽然 CyclicBarrier 多数情况下自动管理生命周期,但仍有几个关键控制点需人工介入:
-
reset():强制重置屏障,使所有正在 await 的线程立即收到BrokenBarrierException。适用于取消整组任务、快速失败恢复等场景 -
isBroken():检查屏障是否已被破坏(如某线程中断、超时、barrierAction 异常),便于在 await 前做预判 -
getNumberWaiting():获取当前阻塞等待的线程数,可用于监控或调试 - 任何线程在 await 过程中被中断,都会导致整个屏障失效,因此建议在线程池中统一配置未捕获异常处理器











