测试并发应用(二)监控Phaser类

声明:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: Javier Fernández González 译者:郑玉婷

监控Phaser类

Java 并发 API 提供的其中一个最复杂且强大的功能是使用 Phaser 类来执行同步phased任务。当有些任务可以分成步骤执行时,此机制是很有用的。Phaser类提供的同步线程机制是在每个步骤的末端, 所以全部的线程都完成第一步后,才能开始执行第二步。

在这个指南,你将学习如何从Phaser类获取其状态信息。

准备

指南中的例子是使用Eclipse IDE 来实现的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打开并创建一个新的java项目。

怎么做呢…

按照这些步骤来实现下面的例子:

[code language=”java”]
//1. 创建一个类,名为 Task ,实现 Runnable 接口.
public class Task implements Runnable {

//2. 声明一个私有 int 属性,名为 time。
private int time;

//3. 声明私有 Phaser 属性,名为 phaser.
private Phaser phaser;

//4. 实现类的构造函数,初始其属性值。
public Task(int time, Phaser phaser) {
this.time=time;
this.phaser=phaser;
}

//5. 实现 run() 方法。首先,使用 arrive() 方法指示 phaser 属性任务开始执行了。
@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 {

//9. 创建新的有3个参与者的 Phaser 对象,名为 phaser。
Phaser phaser=new Phaser(3);

//10. 创建并运行3个线程来执行3个task对象。
for (int i=0; i<3; i++) {
Task task=new Task(i+1, phaser);
Thread thread=new Thread(task);
thread.start();
}

//11.创建迭代10次的for循环,来学关于phaser对象的信息。
for (int i=0; i<10; i++) {

//12. 写关于 registered parties 的信息,phaser的phase,到达的parties, 和未到达的parties 的信息。
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");

//13. 让线程休眠1秒,并合上类的循环。
TimeUnit.SECONDS.sleep(1);
}
}
}
[/code]

它是如何工作的…

在这个指南,我们在 Task 类实现了 phased 任务。此 phased 任务有3个phases,并使用Phaser接口来与其他Task对象同步。当这些任务正在执行他们的phases时候,主类运行3个任务并打印关于phaser对象的状态信息到操控台。 我们使用以下的方法来获取phaser对象的状态:

  • getPhase():此方法返回phaser 任务的 actual phase
  • getRegisteredParties(): 此方法返回使用phaser对象作为同步机制的任务数
  • getArrivedParties(): 此方法返回已经到达actual phase末端的任务数
  • getUnarrivedParties(): 此方法返回还没到达actual phase末端的任务数

以下的裁图展示了项目的部分输出:

参见

第三章,线程同步应用:运行阶段性并发任务

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 测试并发应用(二)监控Phaser类

  • Trackback 关闭
  • 评论 (2)
    • yjk99@qq.com
    • 2013/10/21 11:03上午

    Task 类 phaser.arrive() 调这个方法的时候报了异常
    Exception in thread “Thread-2” java.lang.IllegalStateException: Attempted arrival of unregistered party for java.util.concurrent.Phaser@13ad33d[phase = 0 parties = 0 arrived = 0]
    at java.util.concurrent.Phaser.doArrive(Phaser.java:389)
    at java.util.concurrent.Phaser.arrive(Phaser.java:622)
    at org.thread.test.concurrence.Task.run(Task.java:17)
    at java.lang.Thread.run(Thread.java:724)

      • 郑玉婷
      • 2013/10/31 8:07上午

      不会吧。我刚刚运行了下,没有任何异常。

return top