Phaser 不自动处理线程异常,需主动监控未到达数并超时熔断;各工作线程须 try-catch 并调用 arriveAndDeregister();onAdvance 做轻量校验;长流程应分阶段使用独立 Phaser 或树形结构。

Phaser 本身不会自动感知或响应线程内未捕获的异常——它只认“到达”和“注销”,不关心任务是否成功。一旦某个工作线程因异常崩溃,既没调 arriveAndAwaitAdvance(),也没调 arriveAndDeregister(),它就悄悄从同步中消失,但注册信息仍留在 Phaser 内部。结果是:未到达数(getUnarrivedParties())长期大于 0,其余线程在 arriveAndAwaitAdvance() 处无限等待,形成典型的“幽灵阻塞”死结。
主动监控未到达数 + 超时熔断
不能依赖异常自动传播,必须由协调方(通常是主线程或监控线程)定期探测:
- 用
phaser.getUnarrivedParties()检查是否有线程“失联” - 配合
phaser.getPhase()判断当前卡在哪一阶段 - 若同一 phase 下
getUnarrivedParties() > 0持续超过合理阈值(如 5–30 秒,视任务耗时而定),视为异常卡死 - 立即调用
phaser.forceTermination()—— 这会让所有阻塞中的arriveAndAwaitAdvance()立即返回负值(如 -1),而非继续挂起
让每个任务线程自带兜底保护
异常不应穿透到 Phaser 同步层。每个 worker 线程执行体必须包裹 try-catch:
- 正常流程走
phaser.arriveAndAwaitAdvance() - catch 块里先做必要清理(如关闭资源、记录日志),再调用
phaser.arriveAndDeregister()主动退出当前阶段 - 避免在 catch 中直接 return 或 throw,否则仍会跳过同步动作
用 onAdvance 做阶段级守门人
重写 onAdvance(int phase, int registeredParties),在关键阶段入口加校验:
- 例如 phase == 1 时,检查
registeredParties < 3(预期至少 3 个清洗线程),说明有线程未注册或已注销,可提前终止:return true; - 也可在此触发告警、落库记录或启动补偿逻辑
- 注意:该方法运行在 Phaser 内部同步块中,不可阻塞或耗时,只做轻量判断
避免单点依赖,拆分责任边界
不要让一个 Phaser 承担全部阶段与全部角色。对长流程做职责切分:
- 加载阶段用独立 Phaser A,清洗阶段用 Phaser B,汇总阶段用 Phaser C
- 各阶段间通过状态标志或队列传递结果,而非强同步耦合
- 某阶段失败只影响自身 Phaser,不会拖垮全局
- 必要时可用树形 Phaser(
new Phaser(parent))实现分组+全局两级协调

















