监控Phaser类

Java 9并发编程指南 目录

Java并发API提供的最复杂和最强大的功能之一是使用Phaser类执行并发阶段任务。 当处理分阶段并发任务时,这种机制很有效。Phaser类提供了在每个阶段结束时同步线程的机制,在所有线程都完成第一个阶段之前,没有线程开始第二步。

本节讲学习关于Phaser类的状态信息,以及如何获取这些信息。

准备工作

本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。

实现过程

通过如下步骤实现范例:

  1. 创建名为MyLock的类,实现Runnable接口:

    public class Task implements Runnable{
    
  2. 声明名为time的私有int属性:

    	private final int time;
    
  3. 声明名为phaser的私有Phaser属性:

    	private final Phaser phaser;
    
  4. 实现类构造函数,初始化属性:

    	public Task(int time, Phaser phaser) {
    		this.time=time;
    		this.phaser=phaser;
    	}
    
  5. 实现run()方法,首先,指示phaser属性,此任务使用arrive()方法开始执行:

    	@Override
    	public void run() {
    		phaser.arrive();
    
  6. 输出指明第一阶段开始的信息到控制台。设置线程休眠time属性指定的秒数,然后输出指明第一阶段结束的信息到控制台。使用phaser属性的arriveAndAwaitAdvance()方法同步剩余任务:

    		System.out.printf("%s: Entering phase 1.\n", Thread.currentThread().getName());
    		try {
    			TimeUnit.SECONDS.sleep(time);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.printf("%s: Finishing phase 1.\n", Thread.currentThread().getName());
    		phaser.arriveAndAwaitAdvance();
    
  7. 在二、三阶段重复此操作。在第三阶段结束时,使用arriveAndDeregister()代替arriveAndAwaitAdvance():

    		System.out.printf("%s: Entering phase 2.\n", Thread.currentThread().getName());
    		try {
    			TimeUnit.SECONDS.sleep(time);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.printf("%s: Finishing phase 2.\n", Thread.currentThread().getName());
    		phaser.arriveAndAwaitAdvance();
    		System.out.printf("%s: Entering phase 3.\n", Thread.currentThread().getName());
    		try {
    			TimeUnit.SECONDS.sleep(time);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		
    		System.out.printf("%s: Finishing phase 3.\n", Thread.currentThread().getName());
    		phaser.arriveAndDeregister();
    	}
    }
    
  8. 实现本范例主类,创建名为Main的类,包含main()方法:

public class Main {
	public static void main(String[] args) throws Exception{
  1. 创建名为phaser的新Phaser对象,包含三个阶段:

    		Phaser phaser=new Phaser(3);
    
  2. 创建和加载三个线程分别执行三个任务对象:

    		for (int i=0; i<3; i++) {
    			Task task=new Task(i+1, phaser);
    			Thread thread=new Thread(task);
    			thread.start();
    		}
    
  3. 创建输出phaser对象信息的循环,重复10次:

    		for (int i=0; i<10; i++) {
    
  4. 输出关于注册方、phaser阶段、到达方和未到达方的信息到控制台:

    			System.out.printf("********************\n");
    			System.out.printf("Main: Phaser Log\n");
    			System.out.printf("Main: Phaser: Phase: %d\n", phaser.getPhase());
    			System.out.printf("Main: Phaser: Registered Parties: %d\n", phaser.getRegisteredParties());
    			System.out.printf("Main: Phaser: Arrived Parties: %d\n", phaser.getArrivedParties());
    			System.out.printf("Main: Phaser: Unarrived Parties: %d\n", phaser.getUnarrivedParties());
    			System.out.printf("********************\n");
    
  5. 设置线程休眠1秒钟,关闭循环和类:

    			TimeUnit.SECONDS.sleep(1);
    		}
    	}
    }
    

工作原理

本节实现了Task类中的阶段任务,此任务包括三个阶段,,且使用Phaser接口与其它Task对象同步。主类加载三个任务,当这些任务执行对应阶段时,输出phaser对象的状态信息到控制台。我们使用如下方法得到phaser对象的状态:

  • getPhase():返回phaser对象的实际阶段
  • getRegisteredParties():使用phaser对象作为一种同步机制返回任务数量
  • getArrivedParties():返回已经到达实际阶段结尾的任务数量
  • getUnarrivedParties():返回还未到达实际阶段结尾的任务数量

下图显示本范例在控制台输出的部分执行信息:

pics/09_01.jpg

更多关注

  • 第三章“线程同步功能”中的“运行阶段并发任务”小节

猜你喜欢

转载自blog.csdn.net/nicolastsuei/article/details/84646069