phaser
英文意思移相器,相位器,表示“阶段器”,用来解决控制多个线程分阶段共同完成任务的情景问题,其作用相比CountDownLatch和CyclicBarrier更加灵活。如100个人参加高考需要考四场考试,早上考语文,需要等100人都考完语文才能进行下午的数学,下午的数学都考完才能考明天的综合和英语。
操作方法
phaser(int parties)
构造方法,与CountDownLatch一样,传入同步的线程数,也支持层次构造Phaser(Phaser parent)。
register()
动态添加一个参与者。
bulkRegister(int Parties)
动态添加多个参与者。
arriveAndDeregister()
动态撤销线程在phaser的注册,通知phaser对象,该线程已经结束该阶段且不参与后面阶段。
isTerminated()
当phaser没有参与同步的线程时(或者onAdvance返回true),phaser是终止态(如果phaser进入终止态arriveAndAwaitAdvance()和awaitAdvance()都会立即返回,不在等待)isTerminated返回true。
arrive()方法
通知phaser该线程已经完成该阶段,但不等待其他线程。
arriveAndAwaitAdvance()
类似await()方法,记录到达线程数,阻塞等待其他线程到达同步点后再继续执行。
awaitAdvance(int phase) /awaitAdvanceInterruptibly(int phase)
传入阶段数,只有当前阶段等于phase阶段时才阻塞等待。后者如果线程在休眠被中断会抛出InterruptedException异常(phaser的其他方法对中断都不会抛出异常)。
onAdvance(int phase, int registeredParties)
参数phase是阶段数,每经过一个阶段该数加1,registeredParties是当前参与的线程数。此方法有2个作用:1、当每一个阶段执行完毕,此方法会被自动调用,因此,重写此方法写入的代码会在每个阶段执行完毕时执行,相当于CyclicBarrier的barrierAction。2、当此方法返回true时,意味着Phaser被终止,因此可以巧妙的设置此方法的返回值来终止所有线程。例如:若此方法返回值为 phase>=3,其含义为当整个线程执行了4个阶段后,程序终止。
模拟学生参加高考的例子:
public class TestPhaser {
public static void main(String[] args) {
Phaser phaser=new MyPhaser();
for(int i=1;i<=4;i++){
phaser.register();
new Thread(new StudentTask(phaser)).start();
}
}
}
class StudentTask implements Runnable {
private Phaser phaser;
public StudentTask(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "--到达考试");
phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName() + "--第一场语文开考...");
doExam1();
System.out.println(Thread.currentThread().getName() + "--第一场语文考完...");
phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName() + "--第二场数学开考...");
doExam2();
System.out.println(Thread.currentThread().getName() + "--第二场数学考完...");
phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName() + "--第三场综合开考...");
doExam3();
System.out.println(Thread.currentThread().getName() + "--第三场综合考完...");
phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName() + "--第四场英语开考...");
doExam4();
System.out.println(Thread.currentThread().getName() + "--第四场英语考完...");
phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName() + "--高考结束");
}
private void doExam1() {
long duration = (long) (Math.random() * 10);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doExam2() {
long duration = (long) (Math.random() * 10);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doExam3() {
long duration = (long) (Math.random() * 10);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doExam4() {
long duration = (long) (Math.random() * 10);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyPhaser extends Phaser {
@Override
protected boolean onAdvance(int phase, int registeredParties) {
//在每个阶段执行完成后回调的方法
switch (phase) {
case 0:
return studentArrived();
case 1:
return finishFirstExam();
case 2:
return finishSecondExam();
case 3:
return finishThreeExam();
case 4:
return finishFourExam();
case 5:
return finishExam();
default:
return true;
}
}
private boolean studentArrived() {
System.out.println("学生准备好了,学生人数:" + getRegisteredParties());
return false;
}
private boolean finishFirstExam(){
System.out.println("第一场语文所有学生考完");
return false;
}
private boolean finishSecondExam(){
System.out.println("第二场语文所有学生考完");
return false;
}
private boolean finishThreeExam(){
System.out.println("第三场语文所有学生考完");
return false;
}
private boolean finishFourExam(){
System.out.println("第四场英语所有学生考完");
return false;
}
private boolean finishExam(){
System.out.println("第三题所有学生做完,结束考试");
return true;
}
}
运行结果:
Thread-2--到达考试
Thread-3--到达考试
Thread-1--到达考试
Thread-0--到达考试
学生准备好了,学生人数:4
Thread-0--第一场语文开考...
Thread-2--第一场语文开考...
Thread-1--第一场语文开考...
Thread-3--第一场语文开考...
Thread-1--第一场语文考完...
Thread-3--第一场语文考完...
Thread-2--第一场语文考完...
Thread-0--第一场语文考完...
第一场语文所有学生考完
Thread-3--第二场数学开考...
Thread-1--第二场数学开考...
Thread-2--第二场数学开考...
Thread-0--第二场数学开考...
Thread-1--第二场数学考完...
Thread-3--第二场数学考完...
Thread-2--第二场数学考完...
Thread-0--第二场数学考完...
第二场语文所有学生考完
Thread-1--第三场综合开考...
Thread-3--第三场综合开考...
Thread-2--第三场综合开考...
Thread-0--第三场综合开考...
Thread-3--第三场综合考完...
Thread-2--第三场综合考完...
Thread-1--第三场综合考完...
Thread-0--第三场综合考完...
第三场语文所有学生考完
Thread-3--第四场英语开考...
Thread-1--第四场英语开考...
Thread-2--第四场英语开考...
Thread-0--第四场英语开考...
Thread-3--第四场英语考完...
Thread-0--第四场英语考完...
Thread-1--第四场英语考完...
Thread-2--第四场英语考完...
第四场英语所有学生考完
Thread-2--高考结束
Thread-0--高考结束
Thread-1--高考结束
Thread-3--高考结束