CyclicBarrier天生支持循环复用,无需手动重置;每轮需固定线程数参与并调用一次await(),屏障触发后自动回归初始状态,配合barrier action执行阶段收尾,异常或中断会导致破损且不可自动恢复。

CyclicBarrier 天生就是为循环任务设计的,不需要手动重置就能反复使用。只要所有参与线程都调用了 await(),屏障自动触发、执行回调(如有)、释放线程,然后立刻回到初始状态,等待下一轮同步。
明确参与线程数与阶段结构
复用的前提是任务具有可重复的阶段性特征。每轮同步必须有固定数量的线程参与,且各轮逻辑一致。
- 初始化时指定准确的
parties值,比如 3 个数据处理线程就设为 3,不能多也不能少 - 避免在不同轮次中混用不同数量的线程,否则某轮可能永远等不到“满员”,导致死锁
- 把整个流程拆成清晰阶段:例如“加载→校验→入库”,每个阶段结尾加一次
await()
利用 barrier action 做阶段收尾工作
屏障动作(Runnable 参数)在每轮最后一名线程到达时执行,适合做汇总、日志、状态切换等一次性操作。
- 它由最后一个到达的线程在释放其他线程前执行,不是另起线程,所以要控制耗时,避免拖慢整体进度
- 可用于更新共享变量(如全局计数器、结果容器),确保后续阶段看到最新状态
- 不要在其中抛出未捕获异常,否则会中断屏障正常重置,影响下一轮
正确处理异常与中断
一旦某个线程在 await() 期间被中断或超时,屏障会被标记为“破损”,其他等待线程将收到 BrokenBarrierException,且屏障不再自动复用。
- 捕获
BrokenBarrierException和InterruptedException,并根据业务决定是否重试或终止流程 - 不建议依赖
reset()恢复破损的屏障——它会强制唤醒所有等待线程并抛异常,通常更适合用于主动终止当前轮次 - 若需容错,可在 catch 块中重建新实例,但要注意旧屏障残留线程可能已失效
避免常见复用陷阱
看似自动重置,实则依赖严格的状态流转。几个高频踩坑点需特别注意:
- 误以为
reset()是复用必需步骤——实际仅在异常后或需提前清空时才调用 - 把 CyclicBarrier 当 CountDownLatch 用:后者是一次性倒计时,不可复用;前者是加法式循环栅栏
- 在单轮中多次调用
await()而未配对——每个线程每轮只应调用一次,否则计数错乱 - 跨轮共享同一组线程但未保证每轮都参与——漏掉某线程会导致该轮永远阻塞

















