[笔记][Java7并发编程实战手册]3.7 并发阶段任务中的阶段切换phaser

[笔记][Java7并发编程实战手册]系列目录


简介

  本章主要学习phaser中的阶段切换。在一些场景中,从当前阶段切换到下一阶段过度的时候执行一些操作,那么本章的知识就用上了。
  在phaser中,有一个onAdvance方法, 该方法在参与者数量为0的时候,返回true,来表示该phaser状态为终止状态。
  下面是默认的处理,还有一个phase参数没有用到,我们可以覆写该方法,通过判断当前阶段来做一些操作,当然得记得上一章中,讲到阶段的几个注意事项。

    protected boolean onAdvance(int phase, int registeredParties) {
        return registeredParties == 0;
    }

本章phaser 使用心得总结

  1. 继承并覆盖phaser的 onAdvance 方法,来实现阶段切换的功能
  2. onAdvance方法中的 phase 是阶段的序号,在使用序号来判断的时候,需要注意动态注册的线程的序号会超出预期的阶段序号

示例

游戏闯关示例

场景描述:3个参赛者,参加闯关比赛,但是这个赛制比较奇怪,就是所有参赛者必须等到全部通关,才能开始下一关,官方会在每一个关卡开始前发号命令,报幕闯关开始,闯关结束后,也有谢幕的打印。

/**
 * Created by zhuqiang on 2015/8/23 0023.
 */
public class Client {
    public static void main(String[] args) throws InterruptedException {
        Phaser phaser = new MyPhaser(3);
        ArrayList<Thread> list = new ArrayList<Thread>(3);
        for (int i = 0; i < 3; i++) {
            Thread t = new Thread(new Person(phaser));
            list.add(t);
            t.start();
        }

        for (Thread t : list) {
            t.join();
        }

        System.out.println("phaser 是否是终止状态:" + phaser.isTerminated());

    }
}

/**自定义 phaser,实现阶段切换的功能*/
class MyPhaser extends Phaser {
    public MyPhaser(int parties) {
        super(parties);
    }

    @Override
    protected boolean onAdvance(int phase, int registeredParties) {
        if (registeredParties == 0) { //参与者为0,当前phaser可以被终止了
            System.out.println("《《《官方:本届闯关比赛完美谢幕!");
            return true;
        } else {
            switch (phase){
                case 0:
                    System.out.println("《《《官方:第1关开始·");
                    return false;
                case 1:
                    System.out.println("《《《官方:第2关开始·");
                    return false;
                case 2:
                    System.out.println("《《《官方:第3关开始·");
                    //this.arriveAndDeregister();  //第三关取消注册  注意:不能在 phaser中 调用取消注册的方法,否则抛出 java.lang.IllegalStateException异常,原因是:doArrive(int adjust) 该方法会对unarrived值进校验(好把。源码没有仔细看(看不懂)。所以后面的就不知道为什么会出错了)
                    return false;
            }

        }
        return super.onAdvance(phase, registeredParties);
    }
}
/** 闯关者**/
class Person implements Runnable {
    Phaser phaser = null;

    public Person(Phaser phaser) {
        this.phaser = phaser;
    }

    @Override
    public void run() {
        setp(1); //闯第1关
        setp(2); //闯第2关
        setp(3); //闯第3关
    }

    /**
     * 关卡方法。这里偷点懒,写一个通用方法 来想有几个关卡就传几进来
     * @param level 指定是第几关。
     */
    public void setp(int level){
        phaser.arriveAndAwaitAdvance();  //等待并休眠
        long time = (long)(Math.random() * 1000);
        try {
            TimeUnit.MILLISECONDS.sleep(time);  //随机休眠,模拟闯关耗时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
         System.out.printf("    %s,闯过了第%s关,耗时:%s\n",Thread.currentThread().getName(),level,time);
        if(level == 3){  //第三关是最后一贯,取消线程的注册
            phaser.arriveAndDeregister();
        }
    }

}

某一次的运行结果:

《《《官方:第1关开始·
    Thread-0,闯过了第1关,耗时:496
    Thread-2,闯过了第1关,耗时:510
    Thread-1,闯过了第1关,耗时:799
《《《官方:第2关开始·
    Thread-2,闯过了第2关,耗时:804
    Thread-0,闯过了第2关,耗时:918
    Thread-1,闯过了第2关,耗时:969
《《《官方:第3关开始·
    Thread-0,闯过了第3关,耗时:102
    Thread-1,闯过了第3关,耗时:534
    Thread-2,闯过了第3关,耗时:589
《《《官方:本届闯关比赛完美谢幕!
phaser 是否是终止状态:true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值