Phaser类提供了一个onAdvance(),这个方法接收两个int类型参数:分别是当前执行阶段数以及注册的参与者数量。方法返回一个布尔值,如果返回false表明Phaser中还有任务在执行,返回true表示这一阶段Phaser执行完毕。
Phaser对象进行阶段切换的时候,在所有在arriveAndAwaitAdvance()方法里休眠线程被唤醒之前,onAdvance()方法将被自动调用。onAdvance()方法返回布尔值表明Phaser终止与否,false表示没有终止,因而县城可以继续执行其他阶段。如果返回true,则Phaser仍然唤醒等待的线程,但是状态已经改变为终止状态,所以继续调用phaser的方法将立即返回,并且isTermination()方法也将返回true。
这个方法的默认实现如下,如果参与者数量是0返回true,否则返回false。但是我们可以通过继承Phaser类类覆盖这个方法。当从一个阶段切换到另一个阶段是需要做一些操作,那么我们就这么做。
protected boolean onAdvance(int phase, int registeredParties) {
return registeredParties == 0;
}
我们实现一个学生参加考试的例子,需要等待所有学生都到齐后才能参加考试,每个学生都参加三场考试,然后考试结束。
首先我们实现自己的Phaser类MyPhaser,这个类中我们重写onAdvance()方法,并定义每次阶段切换执行的代码。开始打印考试开始参加学生的数量,然后打印第一场考试结束信息,接着打印第二场考试结束信息,最后打印考试结束信息。前三个方法返回false,表明Phaser还在执行,最后一个方法返回true,表明Phaser执行结束。
public class MyPhaser extends Phaser {
@Override
protected boolean onAdvance(int phase, int registeredParties) {
switch (phase) {
case 0:
return studentsArrived();
case 1:
return finishFirstExercies();
case 2:
return finishSecondExercies();
case 3:
return finishExam();
default:
return true;
}
}
private boolean studentsArrived() {
System.out.printf("Phaser: The exam are going to start. The %d students are ready.\n",
getRegisteredParties());
return false;
}
private boolean finishFirstExercies() {
System.out.printf("Phaser: All the studnets have finished the first exercies.\n");
return false;
}
private boolean finishSecondExercies() {
System.out.printf("Phaser: All the students have finished the second exercies.\n");
return false;
}
private boolean finishExam() {
System.out.printf("Phaser: All the students have finished the exam.\n");
return true;
}
}
定义Student类,使用phaser模拟四步操作 ,分别是考生到场,第一场考试,第二场考试,第三场考试。
public class Student implements Runnable{
private Phaser phaser;
public Student(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
System.out.printf("%s: Has arrived to the exam. %s\n", Thread.currentThread().getName(), new Date());
phaser.arriveAndAwaitAdvance();
System.out.printf("%s: is going to do the first exercise.\n", Thread.currentThread().getName());
doExercise1();
System.out.printf("%s: has done the first exercise.\n", Thread.currentThread().getName());
phaser.arriveAndAwaitAdvance();
System.out.printf("%s: is going to do the second exercise.\n", Thread.currentThread().getName());
doExercise2();
System.out.printf("%s: has done the second exercise.\n", Thread.currentThread().getName());
phaser.arriveAndAwaitAdvance();
System.out.printf("%s: is going to do the third exercise.\n", Thread.currentThread().getName());
doExercise3();
System.out.printf("%s: has finished the exam.\n", Thread.currentThread().getName());
phaser.arriveAndAwaitAdvance();
}
private void doExercise1() {
long duration = (long)(Math.random() * 20);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doExercise2() {
long duration = (long)(Math.random() * 20);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doExercise3() {
long duration = (long)(Math.random() * 20);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
实现主方法类,在这里我们创建5个考生线程,并启动它们。我们并没有在Phaser初始化的时候指定并发线程数量,而是在创建线程的时候使用register()方法来注册到Phaser上。
public class Main{
public static void main(String[] args) {
Phaser phaser = new MyPhaser();
Student[] students = new Student[5];
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
students[i] = new Student(phaser);
phaser.register();
threads[i] = new Thread(students[i], "Student-" + i);
}
for (int i = 0; i < 5; i++) {
threads[i].start();
}
for (int i = 0; i < 5; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Main: The phaser has finished: %s.\n", phaser.isTerminated());
}
}
查看日志
Student-4: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-0: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-2: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-1: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-3: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Phaser: The exam are going to start. The 5 students are ready.
Student-3: is going to do the first exercise.
Student-0: is going to do the first exercise.
Student-0: has done the first exercise.
Student-4: is going to do the first exercise.
Student-2: is going to do the first exercise.
Student-1: is going to do the first exercise.
Student-1: has done the first exercise.
Student-4: has done the first exercise.
Student-3: has done the first exercise.
Student-2: has done the first exercise.
Phaser: All the studnets have finished the first exercies.
Student-2: is going to do the second exercise.
Student-0: is going to do the second exercise.
Student-4: is going to do the second exercise.
Student-1: is going to do the second exercise.
Student-1: has done the second exercise.
Student-3: is going to do the second exercise.
Student-2: has done the second exercise.
Student-0: has done the second exercise.
Student-4: has done the second exercise.
Student-3: has done the second exercise.
Phaser: All the students have finished the second exercies.
Student-3: is going to do the third exercise.
Student-2: is going to do the third exercise.
Student-1: is going to do the third exercise.
Student-0: is going to do the third exercise.
Student-4: is going to do the third exercise.
Student-4: has finished the exam.
Student-0: has finished the exam.
Student-2: has finished the exam.
Student-1: has finished the exam.
Student-3: has finished the exam.
Phaser: All the students have finished the exam.
Main: The phaser has finished: true.
我们尝试把第一场考试执行完毕后的onAdvance方法返回值改为true试试结果,可以看到所有线程执行完第二场考试之后直接就开始执行第三场考试了,并没有等待其他线程都执行完毕第二场考试。
Student-4: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-3: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-1: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-2: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-0: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Phaser: The exam are going to start. The 5 students are ready.
Student-0: is going to do the first exercise.
Student-2: is going to do the first exercise.
Student-4: is going to do the first exercise.
Student-3: is going to do the first exercise.
Student-1: is going to do the first exercise.
Student-1: has done the first exercise.
Student-0: has done the first exercise.
Student-2: has done the first exercise.
Student-4: has done the first exercise.
Student-3: has done the first exercise.
Phaser: All the studnets have finished the first exercies.
Student-3: is going to do the second exercise.
Student-2: is going to do the second exercise.
Student-0: is going to do the second exercise.
Student-1: is going to do the second exercise.
Student-4: is going to do the second exercise.
Student-3: has done the second exercise.
Student-3: is going to do the third exercise.
Student-1: has done the second exercise.
Student-1: is going to do the third exercise.
Student-0: has done the second exercise.
Student-0: is going to do the third exercise.
Student-0: has finished the exam.
Student-2: has done the second exercise.
Student-2: is going to do the third exercise.
Student-4: has done the second exercise.
Student-4: is going to do the third exercise.
Student-3: has finished the exam.
Student-2: has finished the exam.
Student-1: has finished the exam.
Student-4: has finished the exam.
Main: The phaser has finished: true.