phaser 是比 countdownlatch 更灵活的同步工具,支持多阶段推进、动态注册/注销参与者、可查询阶段号,并能通过 onadvance() 定制阶段切换逻辑。

Phaser 是 Java 并发包中比 CountDownLatch 更灵活的同步工具,特别适合需要多阶段、动态注册/注销参与线程、或重复使用的场景。CountDownLatch 一旦计数归零就不可重用,且无法动态增减等待线程;而 Phaser 支持分阶段推进、运行时注册新参与者、可查询当前阶段、还能配合 onAdvance() 实现阶段间逻辑控制。
用 Phaser 模拟 CountDownLatch 的基础等效写法
如果只是想“替换”一个固定数量的 CountDownLatch(比如 3 个线程必须全部到达才继续),可这样初始化并使用:
- 初始化:Phaser phaser = new Phaser(3); —— 构造时传入初始参与者数,等价于
new CountDownLatch(3) - 等待屏障:phaser.arriveAndAwaitAdvance(); —— 当前线程到达并阻塞,直到所有 3 个参与者都调用该方法
- 无需显式 countDown() 或 await(),语义更统一
实现多阶段协同:每个阶段独立等待与推进
这是 Phaser 真正的优势所在。例如:准备 → 执行 → 收集 三个阶段,各阶段内线程需彼此等待,但阶段之间可携带状态或做清理。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 线程在每阶段开始前调用 phaser.arriveAndAwaitAdvance(),自动进入下一阶段(phase 值 +1)
- 可通过 phaser.getPhase() 获取当前阶段编号(从 0 开始),用于分支逻辑
- 阶段切换是原子的:所有线程完成当前阶段后,才统一进入 phase+1,不会出现部分线程卡在旧阶段
支持动态增减参与者:运行时注册新线程或注销已退出者
CountDownLatch 不允许中途变更计数,而 Phaser 可以:
- 新增参与者:phaser.register(); —— 主动为当前线程注册(也可用
phaser.bulkRegister(n)一次加 n 个) - 注销当前线程:phaser.arriveAndDeregister(); —— 到达屏障并退出后续阶段,不影响其他线程继续推进
- 典型场景:工作线程池中,某些任务提前完成并退出协作流程,其余线程仍按阶段继续执行
定制阶段推进逻辑:onAdvance() 钩子函数
重写 Phaser.onAdvance(int phase, int registeredParties),可在每次阶段切换前执行自定义操作:
- 返回 true 表示终止 Phaser(后续 arriveAndAwaitAdvance 将立即返回)
- 返回 false 表示继续下一阶段
- 可用于:阶段间资源检查、超时熔断、统计汇总、日志记录等
- 示例:在 phase == 2(即执行完第 2 阶段,即将进入第 3 阶段前),校验中间结果是否有效,无效则返回 true 终止整个流程
不复杂但容易忽略的是:Phaser 默认不强制所有线程都参与每一阶段——只要还有注册的参与者,它就会持续推进;若需“某阶段必须全员到场”,就得靠业务逻辑配合 register()/deregister() 控制注册时机。合理设计参与者生命周期,才是用好 Phaser 的关键。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










