Java多线程实战|Phaser原理介绍及使用场景
Posted 我是老实人辶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程实战|Phaser原理介绍及使用场景相关的知识,希望对你有一定的参考价值。
前言:
哈喽,安瑞巴得,之前我们学习了多线程工具包java.util.concurrent里的一些工具类的使用场景及原理介绍(没看过的有兴趣可以回看一下),今天讲一下【Java多线程实战】系列的最后一篇Phaser的使用及原理,Phaser表示“阶段器”,用来解决控制多个线程分阶段共同完成任务的情景问题。Phaser相当于CountDownLatch和CyclicBarrier的进阶版本,功能跟强大,使用更灵活,可以满足我们更多的场景需求;
介绍:
Java 7 引入了一个全新灵活的线程同步机制,名为 Phaser 。如果你需要等待线程结束然后继续执行其他任务,那么 Phaser 是一个好的选择。他引入了新的Phaser的概念,我们可以将其看成一个一个的阶段,每个阶段都有需要执行的线程任务,任务执行完毕就进入下一个阶段。所以Phaser特别适合使用在重复执行或者重用的情况。
在之前讲CyclicBarrier我们举了一个点餐的case,所有小伙伴到齐之后才可以进行点餐,Phaser相当于CyclicBarrier的进阶版本,举个相似的例子就是:
当小伙伴们都到齐之后,进行点餐的时候,可以大家一起每人先点一杯喝的,全部点完喝的之后,进入下一个阶段每人在点一到热菜,点完热菜之后,每人在点一个甜点这不过分吧,然后进入下一阶段每人在点一份甜点,这就是Phaser阶段器;
代码示例(为了测试直观,代码我都写在一起了,大家写的时候记得每个方法要分开):
package com.wechat.wechatservice.controller.Executor;
import com.sun.tools.internal.jxc.SchemaGenerator;
import java.util.concurrent.Phaser;
/**
* TODO
*
* @author taoze
* @version 1.0
* @date 6/28/21 2:33 PM
*/
public class PhaserTest extends Phaser {
@Override
protected boolean onAdvance(int phase, int registeredParties) { //在每个阶段执行完成后回调的方法
switch (phase) {
case 0:
return daoqi();
case 1:
return yingping();
case 2:
return zhucai();
case 3:
return tiandian();
default:
return true;
}
}
private boolean tiandian() {
System.out.println("甜点点完了!人数:" + getRegisteredParties());
return false;
}
private boolean zhucai() {
System.out.println("主菜点完了!人数:" + getRegisteredParties());
return false;
}
private boolean yingping() {
System.out.println("饮料点完咯!人数:" + getRegisteredParties());
return false;
}
private boolean daoqi() {
System.out.println("人都到齐咯,开始点菜,人数:" + getRegisteredParties());
return false;
}
static class Runner implements Runnable {
private Phaser phaser;
public Runner(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
System.out.println("同学-"+Thread.currentThread().getName()+":到达");
/**
* 执行这个方法的话会等所有的选手都完成了之后再继续下面的方法
*/
phaser.arriveAndAwaitAdvance();
System.out.println("同学-"+Thread.currentThread().getName()+":点了一杯杨枝甘露");
phaser.arriveAndAwaitAdvance();
System.out.println("同学-"+Thread.currentThread().getName()+":点了一个鱼香肉丝");
phaser.arriveAndAwaitAdvance();
System.out.println("同学-"+Thread.currentThread().getName()+":点了一个巧克力圣代");
phaser.arriveAndAwaitAdvance();
}
}
public static void main(String[] args) {
int runnerNum = 4;
PhaserTest phaser = new PhaserTest();
/**
* 注册一次表示phaser维护的线程个数
*/
phaser.register();
for (int i = 0; i < runnerNum; i++ ) {
/**
* 注册一次表示phaser维护的线程个数
*/
phaser.register();
new Thread(new Runner(phaser)).start();
}
/**
* 后续阶段主线程就不参加了
*/
phaser.arriveAndDeregister();
}
}
执行结果:
解释: boolean onAdvance(int phase, int registeredParties)是Phaser的一个重要的方法经常需要被重载。此方法有2个作用:
- 当每一个阶段执行完毕,此方法会被自动调用,因此,重载此方法写入的代码会在每个阶段执行完毕时执行,相当于CyclicBarrier的barrierAction。
- 当此方法返回true时,意味着Phaser被终止,因此可以巧妙的设置此方法的返回值来终止所有线程。
Phaser有phase和party两个重要状态:phase表示阶段,party表示每个阶段的线程个数,只有每个线程都执行了
phaser.arriveAndAwaitAdvance()才会进入下一个阶段,否则阻塞等待;
整洁成就卓越代码,细节之中只有天地
以上是关于Java多线程实战|Phaser原理介绍及使用场景的主要内容,如果未能解决你的问题,请参考以下文章
深入浅出多线程编程实战ThreadLocal详解(介绍使用原理应用场景)
深入浅出多线程编程实战ThreadLocal详解(介绍使用原理应用场景)
java 优雅的实现多线程等待,可重用的同步屏障Phaser | Java工具类
Java并发编程原理与实战三十八:多线程调度器(ScheduledThreadPoolExecutor)