Phaser是 Java 并发包(java.util.concurrent)中一个灵活、可重用的同步屏障工具类,它结合了CyclicBarrier和CountDownLatch的优点,并提供了更强大的功能。下面从几个维度帮你深入理解Phaser:
一、核心思想:动态注册 + 阶段推进
Phaser = Phase(阶段) + Synchronizer(同步器)
- 它将任务执行划分为多个“阶段”(phase)。
- 每个阶段开始前,所有参与者(parties)必须“到达”(arrive);
- 当所有参与者都到达后,阶段自动推进到下一 phase,然后重复。
- 与
CyclicBarrier不同的是:参与者的数量可以动态增减!
二、关键特性对比
| 特性 | CountDownLatch | CyclicBarrier | Phaser |
|---|---|---|---|
| 是否可重用 | ❌ 一次性 | ✅ 可重用 | ✅ 可重用 |
| 参与者数量是否固定 | ✅ 固定 | ✅ 固定 | ❌动态可变(支持注册/注销) |
| 是否支持阶段编号 | ❌ | ❌ | ✅ 有getPhase() |
| 是否支持自定义阶段完成动作 | ❌ | ✅ 构造时传入 | ✅ 通过onAdvance()重写 |
| 是否支持分层(树形结构减少竞争) | ❌ | ❌ | ✅ 支持 tiering |
| 是否支持中断/超时等待 | ✅(但无法控制屏障) | ✅ | ✅(awaitAdvanceInterruptibly,awaitAdvanceNanos) |
✅Phaser 是三者中最灵活、最强大的同步工具。
三、核心方法分类
1.注册与注销(动态调整参与者)
register():增加一个参与者(返回当前 phase)bulkRegister(int parties):批量注册arriveAndDeregister():到达并退出后续阶段(常用于主线程启动后退出)
📌 注册/注销只影响内部计数,不能查询自己是否已注册。
2.到达(Arrival)——非阻塞
arrive():通知 phaser 自己已到达,不等待其他人,立即返回当前 phase。arriveAndDeregister():到达并从此退出(不再参与后续阶段)。
这两个方法不会阻塞线程。
3.等待(Waiting)——阻塞直到阶段推进
awaitAdvance(int phase):阻塞直到 phaser 进入下一个 phase(或已超过该 phase)。- 即使线程被中断,也会继续等待(不可中断)。
awaitAdvanceInterruptibly(int phase):可中断版本。awaitAdvanceNanos(int phase, long nanosTimeout):带超时版本。
⚠️ 注意:必须传入你“到达时”的 phase 值,否则可能永远等不到!
4.生命周期控制
onAdvance(int phase, int registeredParties):- 每次阶段推进前调用。
- 返回
true表示终止 phaser(后续所有 await 立即返回负值)。 - 默认实现:当
registeredParties == 0时返回true(即没人了就结束)。 - 常用于控制循环次数(如执行 5 个阶段后终止)。
forceTermination():强制终止,释放所有等待线程。isTerminated():检查是否已终止。
5.监控方法(用于调试/监控)
getPhase():当前阶段号(0 → 1 → 2 … → Integer.MAX_VALUE → 0)getRegisteredParties():当前注册的总参与者数getArrivedParties():当前阶段已到达的数量getUnarrivedParties():还未到达的数量
这些值是瞬时快照,不适合用于同步逻辑。
四、典型使用场景
场景 1:替代CountDownLatch(一次性同步)
Phaserphaser=newPhaser(1);// 主线程先注册for(Runnabletask:tasks){phaser.register();newThread(()->{phaser.arriveAndAwaitAdvance();// 等待所有任务创建完毕task.run();}).start();}phaser.arriveAndDeregister();// 主线程退出,触发阶段推进场景 2:多轮迭代(类似CyclicBarrier,但可控制轮数)
Phaserphaser=newPhaser(){protectedbooleanonAdvance(intphase,intregisteredParties){returnphase>=5||registeredParties==0;// 执行5轮后终止}};// 启动多个线程,每轮执行任务后 arriveAndAwaitAdvance()场景 3:分层 Phasers(高并发优化)
- 当参与者成千上万时,单个 Phaser 会成为性能瓶颈。
- 可构建树形结构:每个子 Phaser 负责一小部分线程,父 Phaser 聚合子结果。
- 自动注册/注销父子关系(构造时传入 parent)。
五、重要注意事项
最大参与者数限制:65535(
0xFFFF),超过会抛IllegalStateException。- 解决方案:使用tiered phasers(分层)。
阶段号会回绕:从
Integer.MAX_VALUE回到 0。- 如果你的逻辑依赖 phase 单调递增,需自行处理溢出。
不要在
onAdvance中做耗时操作:它由最后一个到达的线程执行,会阻塞整个阶段推进。异常处理:在
awaitAdvanceInterruptibly或超时方法中捕获异常后,通常应调用forceTermination()避免死锁。
六、一句话总结
Phaser是一个支持动态参与者数量、可重用、可分层、带阶段编号的高级同步屏障,适用于复杂、多阶段、参与者数量变化的并发协调场景。
如果你有具体使用场景(比如“我想让1000个线程分10批执行”),我可以给出代码示例!