书籍
《Java并发编程的艺术》—方腾飞,第8章
场景说明
一批运动员参加一场比赛,比赛分为3个阶段:选手入场-开始比赛-比赛结束。所有的选手完成一个阶段后才能开始下个阶段,否则等待其他选手完成该阶段,比如所有选手入场后才能开始比赛。
实例代码
1、自定义Phaser类
package java7.thread.chapter2.test1;
import java.util.concurrent.Phaser;
public class MyPhaser extends Phaser {
// 总共3个阶段
private int allPhase = 2;
@Override
protected boolean onAdvance(int phase, int registeredParties) {
// 阶段完成后todo,可用switch-case根据每个阶段做不同的事
System.out.println("--第" + (phase + 1) + "阶段已完成--");
// 到达结束阶段,或者没到达结束阶段但是注册线程数为0,返回true
// Phaser阶段改变时自动执行。返回true结束,false继续执行
return phase == allPhase || registeredParties == 0;
}
}
2、任务类
package java7.thread.chapter2.test1;
import java.util.Random;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
public class Player implements Runnable {
private Phaser phaser;
public Player(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
try {
// 随机模拟到场时间
TimeUnit.SECONDS.sleep((new Random().nextInt(5)));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("选手-"+Thread.currentThread().getName()+":已到达赛场");
// 标记阶段,到达某阶段并等待其他线程
phaser.arriveAndAwaitAdvance();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("选手-"+Thread.currentThread().getName()+":已开始比赛");
phaser.arriveAndAwaitAdvance();
try {
TimeUnit.SECONDS.sleep((new Random().nextInt(5)));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("选手-"+Thread.currentThread().getName()+":已完成比赛");
phaser.arriveAndAwaitAdvance();
}
}
3、测试
package java7.thread.chapter2.test1;
/**
* 并发工具类Phaser例子
* (CountDownLatch:await()阻塞,等待计数器减为0时运行,调用countDown()计数器减一)
* (CyclicBarrier:当拦截了n个线程时,await(),这n个线程一起运行。为达到n个之前,被拦截的线程都被阻塞)
* (Semaphore信号量:流量控制,访问某资源的线程不超过多少个,超过的阻塞。acquire() release())
* (Exchanger:交换2个线程的数据,一对一的生产消费)
*/
public class Main {
public static void main(String[] args) {
// 几个线程所属的Phaser对象,通过构造注入
MyPhaser myPhaser = new MyPhaser();
for (int i = 0; i < 5; i++) {
// 新建线程并注册到Phaser
new Thread(new Player(myPhaser)).start();
myPhaser.register();
}
// 当myPhaser所有阶段都已完成,主线程才继续往下运行,打印比赛结束
while (!myPhaser.isTerminated()) {
}
System.err.println("==比赛结束==");
}
}