Java并发API提供的最复杂和最强大的功能之一是使用Phaser类执行并发阶段任务。 当处理分阶段并发任务时,这种机制很有效。Phaser类提供了在每个阶段结束时同步线程的机制,在所有线程都完成第一个阶段之前,没有线程开始第二步。
本节讲学习关于Phaser类的状态信息,以及如何获取这些信息。
准备工作
本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。
实现过程
通过如下步骤实现范例:
-
创建名为MyLock的类,实现Runnable接口:
public class Task implements Runnable{
-
声明名为time的私有int属性:
private final int time;
-
声明名为phaser的私有Phaser属性:
private final Phaser phaser;
-
实现类构造函数,初始化属性:
public Task(int time, Phaser phaser) { this.time=time; this.phaser=phaser; }
-
实现run()方法,首先,指示phaser属性,此任务使用arrive()方法开始执行:
@Override public void run() { phaser.arrive();
-
输出指明第一阶段开始的信息到控制台。设置线程休眠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();
-
在二、三阶段重复此操作。在第三阶段结束时,使用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(); } }
-
实现本范例主类,创建名为Main的类,包含main()方法:
public class Main {
public static void main(String[] args) throws Exception{
-
创建名为phaser的新Phaser对象,包含三个阶段:
Phaser phaser=new Phaser(3);
-
创建和加载三个线程分别执行三个任务对象:
for (int i=0; i<3; i++) { Task task=new Task(i+1, phaser); Thread thread=new Thread(task); thread.start(); }
-
创建输出phaser对象信息的循环,重复10次:
for (int i=0; i<10; i++) {
-
输出关于注册方、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");
-
设置线程休眠1秒钟,关闭循环和类:
TimeUnit.SECONDS.sleep(1); } } }
工作原理
本节实现了Task类中的阶段任务,此任务包括三个阶段,,且使用Phaser接口与其它Task对象同步。主类加载三个任务,当这些任务执行对应阶段时,输出phaser对象的状态信息到控制台。我们使用如下方法得到phaser对象的状态:
- getPhase():返回phaser对象的实际阶段
- getRegisteredParties():使用phaser对象作为一种同步机制返回任务数量
- getArrivedParties():返回已经到达实际阶段结尾的任务数量
- getUnarrivedParties():返回还未到达实际阶段结尾的任务数量
下图显示本范例在控制台输出的部分执行信息:
更多关注
- 第三章“线程同步功能”中的“运行阶段并发任务”小节