Phaser 类提供了一个方法在每次 phaser 改变阶段时执行。这就是 onAdvance() 方法。
您可以通过扩展 Phaser 类并覆盖 onAdvance 方法来改变缺省行为。 通常当您在从一个阶段推进到下一个阶段时必须执行某些动作的情况下,您会有兴趣改变其缺省行为。
本节的示例代码在 com.elanzone.books.noteeg.chpt3.sect07 package中
扩展 Phaser 类 : MyPhaser
@Override protected boolean onAdvance(int phase, int registeredParties) { switch (phase) { case 0: return studentsArrived(); case 1: return finishFirstExercise(); case 2: return finishSecondExercise(); case 3: return finishExam(); default: return true; } }
private boolean studentsArrived() { System.out.printf("Phaser: The exam are going to start. The students are ready.\n"); System.out.printf("Phaser: We have %d students.\n", getRegisteredParties()); return false; }
学生线程类 : Student
private Phaser phaser; public Student(Phaser phaser) { this.phaser = phaser; }
System.out.printf("%s: Has arrived to do the exam. %s\n", Thread.currentThread().getName(), new Date()); phaser.arriveAndAwaitAdvance(); System.out.printf("%s: Is going to do the first exercise. %s\n", Thread.currentThread().getName(), new Date()); doExercise1(); System.out.printf("%s: Has done the first exercise. %s\n", Thread.currentThread().getName(), new Date()); phaser.arriveAndAwaitAdvance(); System.out.printf("%s: Is going to do the second exercise.%s\n", Thread.currentThread().getName(), new Date()); doExercise2(); System.out.printf("%s: Has done the second exercise. %s\n", Thread.currentThread().getName(), new Date()); phaser.arriveAndAwaitAdvance(); System.out.printf("%s: Is going to do the third exercise. %s\n", Thread.currentThread().getName(), new Date()); doExercise3(); System.out.printf("%s: Has finished the exam. %s\n", Thread.currentThread().getName(), new Date()); phaser.arriveAndAwaitAdvance();
private void doExercise1() { try { long duration = (long) (Math.random() * 10); TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } }
控制类 : Main
MyPhaser phaser = new MyPhaser();
Student students[] = new Student[5]; for (int i = 0; i < students.length; i++) { students[i] = new Student(phaser); phaser.register(); }
Thread threads[] = new Thread[students.length]; for (int i = 0; i < students.length; i++) { threads[i] = new Thread(students[i], "Student " + i); threads[i].start(); }
for (Thread thread : threads) { try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.printf("Main: The phaser has finished: %s.\n", phaser.isTerminated());
本例模拟了一个有3个练习的测验。所有学生必须都完成一个练习才能启动下一个。 为了实现此同步需求,使用了 Phaser 类,只是扩展原类覆盖了 onAdvance() 方法实现了自己的 Phaser。
onAdvance() 方法在阶段变化和唤醒所有在 arriveAndAwaitAdvance() 方法内睡眠的线程前被 phaser 调用。 此方法接受实际阶段数作为参数,阶段数和注册参与人数从 0 开始。 最有用的参数时实际阶段。如果您依赖实际的阶段执行一个不同的操作,您必须使用选择语句(if/else或switch)来选择想要执行的操作。 本例使用一个 switch 语句来为每次阶段的变化选择不同的方法。
onAdvance() 方法返回一个 Boolean 值表示 phaser 是否已终结。
在 Main 类中,当创建 MyPhaser 对象时未指定 phaser 内的参与者数目。 您为每个创建的学生对象调用一次 register() 方法来注册一个参与者到 phaser。 此调用不在 Student 对象或对应执行的线程 与 phaser 之间建立联系。 在 phaser 中的参与者数目只是一个数字,在 phaser 和 参与者之间没有关系。