測試併發應用(二)監控Phaser類
阿新 • • 發佈:2018-12-22
宣告:本文是《 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末端的任務數
以下的裁圖展示了專案的部分輸出:
參見