Java多线程中的Phaser使用解析

 更新时间:2023年11月30日 08:34:09   作者:MC-闰土  
这篇文章主要介绍了Java多线程中的Phaser使用解析,java多线程技术提供了Phaser工具类,Phaser表示“阶段器”,用来解决控制多个线程分阶段共同完成任务的情景问题,其作用相比CountDownLatch和CyclicBarrier更加灵活,需要的朋友可以参考下

问题描述

java多线程技术提供了Phaser工具类,Phaser表示“阶段器”,用来解决控制多个线程分阶段共同完成任务的情景问题。

其作用相比CountDownLatch和CyclicBarrier更加灵活,例如有这样的一个题目:

5个学生一起参加考试,一共有三道题,要求所有学生到齐才能开始考试,全部同学都做完第一题,学生才能继续做第二题,全部学生做完了第二题,才能做第三题,所有学生都做完的第三题,考试才结束。

分析这个题目:这是一个多线程(5个学生)分阶段问题(考试考试、第一题做完、第二题做完、第三题做完),所以很适合用Phaser解决这个问题。

实现代码

import java.util.concurrent.Phaser;
 
/***
 *  下面说说Phaser的高级用法,在Phaser内有2个重要状态,分别是phase和party。
 *  phase就是阶段,初值为0,当所有的线程执行完本轮任务,同时开始下一轮任务时,
 *  意味着当前阶段已结束,进入到下一阶段,phase的值自动加1。party就是线程,
 *  party=4就意味着Phaser对象当前管理着4个线程。Phaser还有一个重要的方法经常需要被重载,
 *  那就是boolean onAdvance(int phase, int registeredParties)方法。此方法有2个作用:
 *  1、当每一个阶段执行完毕,此方法会被自动调用,因此,重载此方法写入的代码会在每个阶段执行完毕时执行,
 *  相当于CyclicBarrier的barrierAction。
 *  2、当此方法返回true时,意味着Phaser被终止,因此可以巧妙的设置此方法的返回值来终止所有线程。
 * @author liujun
 */
public class MyPhaser extends Phaser {
 
	@Override
	protected boolean onAdvance(int phase, int registeredParties) {	//在每个阶段执行完成后回调的方法
		
		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;
	}
	
}
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
 
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题时间...");
		doExercise1();
		System.out.println(Thread.currentThread().getName()+"做第1题完成...");
		phaser.arriveAndAwaitAdvance();
		
		System.out.println(Thread.currentThread().getName()+"做第2题时间...");
		doExercise2();
		System.out.println(Thread.currentThread().getName()+"做第2题完成...");
		phaser.arriveAndAwaitAdvance();
		
		System.out.println(Thread.currentThread().getName()+"做第3题时间...");
		doExercise3();
		System.out.println(Thread.currentThread().getName()+"做第3题完成...");
		phaser.arriveAndAwaitAdvance();
	}
 
	private void doExercise1() {
		long duration = (long)(Math.random()*10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	private void doExercise2() {
		long duration = (long)(Math.random()*10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	private void doExercise3() {
		long duration = (long)(Math.random()*10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}
/**
 * 题目:5个学生参加考试,一共有三道题,要求所有学生到齐才能开始考试
 * ,全部做完第一题,才能继续做第二题,后面类似。
 * 
 * Phaser有phase和party两个重要状态,
 * phase表示阶段,party表示每个阶段的线程个数,
 * 只有每个线程都执行了phaser.arriveAndAwaitAdvance();
 * 才会进入下一个阶段,否则阻塞等待。
 * 例如题目中5个学生(线程)都条用phaser.arriveAndAwaitAdvance();就进入下一题
 * @author liujun
 */
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());
		
	}
	
}

结果

Student 0到达考试
Student 1到达考试
Student 4到达考试
Student 2到达考试
Student 3到达考试
学生准备好了5
Student 2做第1题时间...
Student 0做第1题时间...
Student 1做第1题时间...
Student 4做第1题时间...
Student 3做第1题时间...
Student 2做第1题完成...
Student 3做第1题完成...
Student 1做第1题完成...
Student 0做第1题完成...
Student 4做第1题完成...
第一题所有学生做完
Student 3做第2题时间...
Student 0做第2题时间...
Student 4做第2题时间...
Student 1做第2题时间...
Student 2做第2题时间...
Student 3做第2题完成...
Student 2做第2题完成...
Stud ent 0做第2题完成...
Student 1做第2题完成...
Student 4做第2题完成...
第二题所有学生做完
Student 0做第3题时间...
Student 3做第3题时间...
Student 2做第3题时间...
Student 4做第3题时间...
Student 1做第3题时间...
Student 1做第3题完成...
Student 0做第3题完成...
Student 2做第3题完成...
Student 3做第3题完成...
Student 4做第3题完成...
第三题所有学生做完,结束考试
Phaser has finished:true

到此这篇关于Java多线程中的Phaser使用解析的文章就介绍到这了,更多相关Java多线程中的Phaser内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java Matcher匹配头尾截取替换字符串的案例

    java Matcher匹配头尾截取替换字符串的案例

    这篇文章主要介绍了java Matcher匹配头尾截取替换字符串的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • MyBatisPlus中批量插入之如何通过开启rewriteBatchedStatements=true

    MyBatisPlus中批量插入之如何通过开启rewriteBatchedStatements=true

    这篇文章主要介绍了MyBatisPlus中批量插入之如何通过开启rewriteBatchedStatements=true问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • java使用HashMap实现斗地主(有序版)

    java使用HashMap实现斗地主(有序版)

    这篇文章主要为大家详细介绍了java使用ArrayList实现斗地主游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • 一文带你了解Java万物之基之Object类

    一文带你了解Java万物之基之Object类

    Java是一门天然的面向对象的语言。而所有我们手动创造出来的类,都继承于同一个类,即Object类。本文将通过示例为大家详细介绍一下Java中的Object类,需要的可以参考一下
    2022-03-03
  • Spring Boot启动端口修改方法

    Spring Boot启动端口修改方法

    spring boot是个好东西,可以不用容器直接在main方法中启动,而且无需配置文件,方便快速搭建环境。下面通过本文给大家分享Spring Boot修改启动端口的方法,感兴趣的的朋友一起看看吧
    2017-07-07
  • spring boot自动装配之@ComponentScan注解用法详解

    spring boot自动装配之@ComponentScan注解用法详解

    @ComponentScan的作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中,下面这篇文章主要给大家介绍了关于spring boot自动装配之@ComponentScan注解用法的相关资料,需要的朋友可以参考下
    2023-04-04
  • 只用400行Java代码就能实现的飞翔的小鸟游戏

    只用400行Java代码就能实现的飞翔的小鸟游戏

    今天给大家带来的是关于Java实战的相关知识,文章围绕着只用400行Java代码就能实现的飞翔的小鸟游戏展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • Java计时器StopWatch实现方法代码实例

    Java计时器StopWatch实现方法代码实例

    这篇文章主要介绍了Java计时器StopWatch实现方法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • springboot如何获取登录用户的个人信息

    springboot如何获取登录用户的个人信息

    在Spring Boot中,获取登录用户的个人信息通常需要使用Spring Security框架来进行身份认证和授权,这篇文章主要介绍了springboot获取登录用户的个人信息,需要的朋友可以参考下
    2023-05-05
  • Java任意长度byte数组转换为int数组的方法

    Java任意长度byte数组转换为int数组的方法

    这篇文章主要给大家介绍了关于Java任意长度byte数组转换为int数组的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07

最新评论