自定义屏障动作(barrieraction)是屏障释放前必须由最后一个调用await()的线程同步执行的关键临界段,直接影响所有等待线程继续运行,禁止耗时操作,异常会包装为brokenbarrierexception并传播给所有await线程。

自定义屏障动作(barrierAction)不是可选的“回调钩子”,而是屏障释放前必须同步完成的关键临界段。它由最后一个调用 await() 的线程直接执行,不另起线程、不切换上下文,执行结果直接影响所有等待线程能否继续运行。
barrierAction 的触发与执行主体
它只在满足 parties 数量的线程全部调用 await() 后触发,且严格由第 N 个(即凑齐人数)的线程执行:
- 该线程会先执行
barrierAction.run(),完成后才唤醒其余 N−1 个线程 - 若 barrierAction 抛出 RuntimeException,会被包装为
BrokenBarrierException,并传播给所有正在 await() 的线程(包括当前线程) - 它运行在抵达线程的原始栈帧中,共享其 ThreadLocal、ClassLoader、事务上下文和 MDC 日志标记
配置 barrierAction 的实用原则
设计时需把它当作同步关卡来对待,避免常见误用:
- 禁止执行 I/O、远程调用、数据库写入或持有锁的耗时操作——否则会拖慢全部线程响应
- 不要依赖它做关键状态恢复,因为异常发生时不会进入 finally 块,也不会被执行
- 如需统一上下文(如日志链路 ID 或认证信息),应在各工作线程调用 await() 前主动传递,并在 barrierAction 中显式读取或重建
- 若确需异步处理,必须在 barrierAction 内部显式提交到线程池,例如
executor.submit(() -> {...})
典型配置示例与注意事项
构造时传入 Runnable 即可启用屏障动作:
CyclicBarrier barrier = new CyclicBarrier(4, () -> {
System.out.println("汇总开始 —— 当前执行线程: " + Thread.currentThread().getName());
// ✅ 轻量级操作:更新共享计数器、打印日志、设置标志位
// ❌ 避免:new Socket(...).connect()、repository.save(...)、synchronized(obj) {...}
});
- parties 值不可修改,构造后固定;若需动态调整参与数,只能新建实例或调用
reset()(注意已等待线程会收到 BrokenBarrierException) - 返回值
int表示该线程是第几个到达(从 parties−1 递减),可用于主次角色区分,但不可用于控制 barrierAction 执行逻辑 - barrierAction 不具备重入性,每次屏障打开仅执行一次,且不保证在同一线程重复执行
不复杂但容易忽略:它不是后台任务,而是阻塞式同步环节。设计对了,它让多阶段并行更可控;设计错了,它就成了整个流程的瓶颈点。











