1. 程式人生 > >測試併發應用(二)監控Phaser類

測試併發應用(二)監控Phaser類

宣告:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: Javier Fernández González 譯者:鄭玉婷

監控Phaser類

Java 併發 API 提供的其中一個最複雜且強大的功能是使用 Phaser 類來執行同步phased任務。當有些任務可以分成步驟執行時,此機制是很有用的。Phaser類提供的同步執行緒機制是在每個步驟的末端, 所以全部的執行緒都完成第一步後,才能開始執行第二步。

在這個指南,你將學習如何從Phaser類獲取其狀態資訊。

準備

指南中的例子是使用Eclipse IDE 來實現的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 開啟並建立一個新的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);
}
}
}

它是如何工作的…

在這個指南,我們在 Task 類實現了 phased 任務。此 phased 任務有3個phases,並使用Phaser介面來與其他Task物件同步。當這些任務正在執行他們的phases時候,主類執行3個任務並列印關於phaser物件的狀態資訊到操控臺。 我們使用以下的方法來獲取phaser物件的狀態:

  • getPhase():此方法返回phaser 任務的 actual phase
  • getRegisteredParties(): 此方法返回使用phaser物件作為同步機制的任務數
  • getArrivedParties(): 此方法返回已經到達actual phase末端的任務數
  • getUnarrivedParties(): 此方法返回還沒到達actual phase末端的任務數

以下的裁圖展示了專案的部分輸出:

參見