基于CAS的一些锁(4)- Phaser

phase 是阶段的意思。Phaser是按照不同阶段执行线程的,就像是结合了CountDownLatch和CyclicBarrier,它本身维护着一个叫 phase 的成员变量代表当前执行的阶段。

如果程序中遇到分好几个阶段执行,并且有的阶段需要多个线程共同参与的情况下可能会用到Phase。

示例:

这里模拟了一个结婚的场景

自定义一个MarriagePhaser 继承 Phaser 重写Phaser的onAdvance方法定义了4个阶段(进入下一个阶段时该方法被自动调用)。
阶段必须从0开始。onAdvice的两个参数 phase是第几个阶段,registeredParties是目前有几个已注册线程参加。
最后返回值为false表示流程未结束,继续执行下一阶段,返回true表示流程结束。

Persion的run方法中有四种行为对应四个阶段

public class T04_Phaser {static Random r = new Random();static MarriagePhaser phaser = new MarriagePhaser();static class MarriagePhaser extends Phaser {@Overrideprotected boolean onAdvance(int phase, int registeredParties) {// 定义4个阶段,一个阶段结束时该方法被自动调用switch (phase) {case 0:System.out.println("所有人到齐!" + registeredParties + "\n");return false; // 流程未结束,继续case 1:System.out.println("所有人都吃完饭了!" + registeredParties + "\n");return false; // 流程未结束,继续case 2:System.out.println("客人都离开了!" + registeredParties + "\n");return false; // 流程未结束,继续case 3:System.out.println("婚礼结束!" + registeredParties + "\n");return true; // 流程结束default:return true;}}}// 定义Persion类,实现Runnable ,重写run方法参加婚礼static class Persion implements Runnable {String name;public Persion(String name){this.name = name;}// 提取sleep方法public void secondsSleep(int seconds) {try {TimeUnit.SECONDS.sleep(seconds);} catch (InterruptedException e) {e.printStackTrace();}}// 阶段 1 行为public void arrive() {secondsSleep(2);System.out.println(name + "到达现场!");phaser.arriveAndAwaitAdvance(); // 阶段结束放行}// 阶段 2 行为public void eat() {secondsSleep(2);System.out.println(name + "吃完饭!");phaser.arriveAndAwaitAdvance(); // 阶段结束放行}// 阶段 3 行为public void leave() {if ("新郎".equals(name) || "新娘".equals(name)) {secondsSleep(2);System.out.println(name + "留下!");phaser.arriveAndAwaitAdvance(); // 阶段结束放行} else {System.out.println(name + "离开!");/** 客人离开后从phaser中注销,不再受阶段控制** 注意:这时客人的线程并没有结束,只是不再受phaser影响可自由往下执行** 注销后可减少下一阶段中需要提前加入的线程,提高效率*/phaser.arriveAndDeregister(); // 从phaser中注销}}// 阶段 4 行为 public void hug() {if ("新郎".equals(name) || "新娘".equals(name)) {secondsSleep(2);System.out.println(name + "拥抱!");phaser.arriveAndAwaitAdvance();}}@Overridepublic void run() {arrive();eat();leave();hug();}}public static void main(String[] args) {// 注册7个线程phaser.bulkRegister(7);for (int i = 0; i < 5; i++) {new Thread(new Persion("客人" + i)).start();}new Thread(new Persion("新郎")).start();new Thread(new Persion("新娘")).start();}}