JUC之Phaser

简介

Phaser是一个灵活的线程同步工具,他包含了CyclicBarrier和CountDownLatch的相关功能

CountDownLatch是先指定N个线程干活,每个线程干完活就减一(countDown()),等待N个线程干完活,await()后面的其他线程才能执行。

CyclicBarrier是先指定需要N个线程,等N个线程到齐了大家同时干活(并发执行),大家在没有全部到齐的情况下同时阻塞在await(),等都到达了await才会同时执行之后的代码。

Phaser正是结合了这二者的特点,可以理解为先指定N个线程等N个线程到齐了开始干第一阶段的活,等第一阶段所有线程干完活了,接着这N个线程继续开始干下一阶段的活,以此类推直至干完业务逻辑了所有阶段的活(当然每个阶段可以干完进入下一个阶段可以踢掉一下不需要的线程,当然也可以全部留下来,不剔除)。

举例

题目:5个学生一起参加考试,一共有三道题,要求所有学生到齐才能开始考试,全部同学都做完第一题,学生才能继续做第二题,全部学生做完了第二题,才能做第三题,所有学生都做完的第三题,考试才结束。分析这个题目:这是一个多线程(5个学生)分阶段问题(考试、第一题做完、第二题做完、第三题做完、结束),所以很适合用Phaser解决这个问题。

代码

MyPhaser类继承自Phaser,重写了每个阶段完成以后的自动调用方法

/**
 * @PROJECT_NAME: demo
 * @DESCRIPTION: /***
 * 下面说说Phaser的高级用法,在Phaser内有2个重要状态,分别是phase和party。
 * phase就是阶段,初值为0,当所有的线程执行完本轮任务,同时开始下一轮任务时,
 * 意味着当前阶段已结束,进入到下一阶段,phase的值自动加1。
 * party就是线程,party=5就意味着Phaser对象当前管理着4个线程。Phaser还有一个重要的方法经常需要被重载,
 * 那就是boolean onAdvance(int phase, int registeredParties)方法。此方法有2个作用:
 * 1、当每一个阶段执行完毕,此方法会被自动调用,因此,重载此方法写入的代码会在每个阶段执行完毕时执行,
 * 相当于CyclicBarrier的barrierAction。
 * 2、当此方法返回true时,意味着Phaser被终止,因此可以巧妙的设置此方法的返回值来终止所有线程。
 * @AUTHOR: 
 * @DATE: 
 */
public class MyPhaser extends Phaser {
    @Override
    protected boolean onAdvance(int phase, int registeredParties) {	//在每个阶段执行完成后回调的方法,phase是从0开始,每个阶段完成会自增,当返回值为true,phaser终止

        switch (phase) {
            case 0:
                return studentArrived();
            case 1:
                return finishFirstExercise();
            case 2:
                return finishSecondExercise();
            case 3:
                return finishExam();
            default:
                return true;
        }

    }

    private boolean studentArrived(){
        System.out.println("学生准备好了,学生人数:"+getRegisteredParties());
        return false;
    }

    private boolean finishFirstExercise(){
        System.out.println("第一题所有学生做完");
        return false;
    }

    private boolean finishSecondExercise(){
        System.out.println("第二题所有学生做完");
        return false;
    }

    private boolean finishExam(){
        System.out.println("第三题所有学生做完,结束考试");
        return true;
    }

线程执行业务的具体流程

/**
 * @PROJECT_NAME: demo
 * @DESCRIPTION: 每个学生的线程执行逻辑,将phaser注册进其中,可控制程序运行逻辑
 * arriveAndAwaitAdvance()相当于await(),等待都到达以后
 * 回调onAdvance()方法,再执行下一阶段
 */
public 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()+"做第1题时间...");
        doExercise();
        System.out.println(Thread.currentThread().getName()+"做第1题完成...");
        phaser.arriveAndAwaitAdvance();

        System.out.println(Thread.currentThread().getName()+"做第2题时间...");
        doExercise();
        System.out.println(Thread.currentThread().getName()+"做第2题完成...");
        phaser.arriveAndAwaitAdvance();

        System.out.println(Thread.currentThread().getName()+"做第3题时间...");
        doExercise();
        System.out.println(Thread.currentThread().getName()+"做第3题完成...");
        phaser.arriveAndAwaitAdvance();
    }

    private void doExercise() {
        long duration = (long)(Math.random()*10);
        try {
            TimeUnit.SECONDS.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

主方法

/**
 * @PROJECT_NAME: demo
 * @DESCRIPTION:
 * @AUTHOR: xiangyu.ren
 * @DATE: 2022/12/5 10:59
 */
public class Main {
    public static void main(String[] args) {
        MyPhaser phaser = new MyPhaser();
        StudentTask[] studentTask = new StudentTask[5];
        for (int i = 0; i < studentTask.length; i++) {
            studentTask[i] = new StudentTask(phaser);
            phaser.register();	//注册一次表示phaser维护的线程个数
        }

        Thread[] threads = new Thread[studentTask.length];
        for (int i = 0; i < studentTask.length; i++) {
            threads[i] = new Thread(studentTask[i], "Student "+i);
            threads[i].start();
        }

        //等待所有线程执行结束
        for (int i = 0; i < studentTask.length; i++) {
            try {
                // 等待线程执行结束
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("Phaser has finished:"+phaser.isTerminated());

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值