Phaser是 Java 7 引入的一个灵活的同步屏障,比
CyclicBarrier和
CountDownLatch更强大。下面通过几个案例展示如何使用
Phaser。
基础案例:多线程分阶段任务
import java.util.concurrent.Phaser;
public class PhaserDemo {
public static void main(String[] args) {
// 创建Phaser,初始注册数为3
Phaser phaser = new Phaser(3);
// 创建并启动3个线程
for (int i = 0; i < 3; i++) {
new Thread(new Task(phaser), "Thread-" + (i + 1)).start();
}
}
static class Task implements Runnable {
private final Phaser phaser;
public Task(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 开始执行阶段1");
phaser.arriveAndAwaitAdvance(); // 等待所有线程完成阶段1
System.out.println(Thread.currentThread().getName() + " 开始执行阶段2");
phaser.arriveAndAwaitAdvance(); // 等待所有线程完成阶段2
System.out.println(Thread.currentThread().getName() + " 完成所有工作");
}
}
}
动态注册案例
import java.util.concurrent.Phaser;
public class DynamicRegistrationDemo {
public static void main(String[] args) {
// 初始注册数为1(主线程)
Phaser phaser = new Phaser(1);
// 阶段0
System.out.println("阶段" + phaser.getPhase() + "开始");
// 创建并启动3个线程
for (int i = 0; i < 3; i++) {
phaser.register(); // 注册新参与者
new Thread(new Worker(phaser), "Worker-" + i).start();
}
// 主线程等待所有工作线程完成阶段0
phaser.arriveAndAwaitAdvance();
System.out.println("阶段" + phaser.getPhase() + "完成");
}
static class Worker implements Runnable {
private final Phaser phaser;
public Worker(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 开始工作");
// 模拟工作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 完成工作");
phaser.arriveAndDeregister(); // 完成工作并注销
}
}
}
高级案例:分阶段并行计算
import java.util.concurrent.Phaser;
public class ParallelComputation {
public static void main(String[] args) {
int numTasks = 4;
Phaser phaser = new Phaser(numTasks) {
// 重写onAdvance方法,在所有线程到达后执行
protected boolean onAdvance(int phase, int registeredParties) {
System.out.println("======= 阶段" + phase + "完成 =======");
return registeredParties == 0; // 返回true表示终止
}
};
for (int i = 0; i < numTasks; i++) {
new Thread(new ComputationTask(phaser, i)).start();
}
}
static class ComputationTask implements Runnable {
private final Phaser phaser;
private final int id;
public ComputationTask(Phaser phaser, int id) {
this.phaser = phaser;
this.id = id;
}
@Override
public void run() {
// 阶段1
System.out.println("任务" + id + " 阶段1计算");
compute(id * 100);
phaser.arriveAndAwaitAdvance();
// 阶段2
System.out.println("任务" + id + " 阶段2计算");
compute(id * 200);
phaser.arriveAndAwaitAdvance();
// 阶段3
System.out.println("任务" + id + " 阶段3计算");
compute(id * 300);
phaser.arriveAndDeregister(); // 完成并注销
}
private void compute(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
关键方法说明
arriveAndAwaitAdvance()
- 到达并等待其他线程arriveAndDeregister()
- 到达并注销自己register()
- 注册新参与者bulkRegister(int parties)
- 批量注册多个参与者onAdvance(int phase, int registeredParties)
- 可重写的方法,当阶段推进时调用
使用场景
- 多阶段并行计算
- 游戏开发中的多玩家同步
- 分布式任务的分阶段执行
- 任何需要分阶段同步的多线程场景
Phaser
相比 CyclicBarrier
和 CountDownLatch
的优势在于可以动态调整参与线程数量,并且支持更灵活的阶段控制。