1. 程式人生 > >測試併發應用(三)監控Executor框架

測試併發應用(三)監控Executor框架

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

監控Executor框架

Executor 框架提供從執行緒的建立和管理來分別實現任務來執行這些任務的機制。如果你使用一個執行者,你只需要實現 Runnable 物件並把他們傳送給執行者。 執行者的責任是管理執行緒。當你發一個任務給執行者,它會嘗試使用pooled執行緒來執行這個任務,來避免建立新的任務。此機制由 Executor 介面提供,它是以 ThreadPoolExecutor 類來實現的。

在這個指南,你將學習從ThreadPoolExecutor執行者可以獲取的資訊和如何獲取這些資訊。

準備

指南中的例子是使用Eclipse IDE 來實現的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 開啟並建立一個新的java專案。

怎麼做呢…

按照這些步驟來實現下面的例子::

//1. 建立一個類,名為 Task,並實現 Runnable 介面.
public class Task implements Runnable {

//2. 宣告一個私有 long 屬性,名為 milliseconds.
private long milliseconds;

//3. 實現類的建構函式,初始化它的屬性。
public Task (long milliseconds) {
this.milliseconds=milliseconds;
}

//4. 實現 run() 方法。通過 milliseconds 屬性讓執行緒進入一段時間休眠。
@Override
public void run() {
System.out.printf("%s: Begin\n",Thread.currentThread(). getName());
try {
TimeUnit.MILLISECONDS.sleep(milliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s: End\n",Thread.currentThread(). getName());
}

//5. 建立例子的主類通過建立一個類,名為 Main 並新增 main()方法。
public class Main {

public static void main(String[] args) throws Exception {

//6. 使用Executors類的newCachedThreadPool()方法建立新的 Executor 物件。
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors. newCachedThreadPool();

//7. 建立並提交10個 Task 物件給執行者。用隨機數字初始化任務。
Random random=new Random();
for (int i=0; i<10; i++) {
Task task=new Task(random.nextInt(10000));
executor.submit(task);
}

//8. 建立迭代為5的for迴圈。在每步,傳遞執行者呼叫 showLog() 方法寫相關資訊,並讓執行緒休眠1秒。
for (int i=0; i<5; i++){
showLog(executor);
TimeUnit.SECONDS.sleep(1);
}

//9. 使用 shutdown() 方法關閉執行者。
executor.shutdown();

//10. 另建立迭代為5的for迴圈。在每步,傳遞執行者呼叫 showLog() 方法寫相關資訊,並讓執行緒休眠1秒。
for (int i=0; i<5; i++){
showLog(executor);
TimeUnit.SECONDS.sleep(1);
}

//11. 使用 awaitTermination() 方法等待執行者的終結。
executor.awaitTermination(1, TimeUnit.DAYS);

//12. 顯示一條結束程式的資訊。
System.out.printf("Main: End of the program.\n");
}

//13. 實現 showLog() 方法,接收 Executor 作為引數。寫關於pool的大小,任務的數量,和執行者狀態的資訊。
private static void showLog(ThreadPoolExecutor executor) {
System.out.printf("*********************");
System.out.printf("Main: Executor Log");
System.out.printf("Main: Executor: Core Pool Size:%d\n",executor.getCorePoolSize());
System.out.printf("Main: Executor: Pool Size: %d\n",executor. getPoolSize());
System.out.printf("Main: Executor: Active Count:%d\n",executor.getActiveCount());
System.out.printf("Main: Executor: Task Count: %d\n",executor. getTaskCount());
System.out.printf("Main: Executor: Completed Task Count:%d\n",executor.getCompletedTaskCount());
System.out.printf("Main: Executor: Shutdown: %s\n",executor. isShutdown());
System.out.printf("Main: Executor: Terminating:%s\n",executor.isTerminating());
System.out.printf("Main: Executor: Terminated: %s\n",executor. isTerminated());
System.out.printf("*********************\n");
}

它是如何工作的…

在這個指南里,你實現了一個任務,它對它的執行執行緒進行了一段隨機毫秒數的阻塞。然後,你傳送10個任務給執行者,並且當你正在等待它們的終結的同時,你已經把關於執行者的狀態的資訊寫入到操控臺。你使用了以下的方法來獲取 Executor 物件的狀態:

  • getCorePoolSize(): 此方法返回一個int數,表示執行緒的核心數。它是當執行者沒有執行任何任務時,在內部執行緒池的執行緒數。
  • getPoolSize(): 此方法返回一個int數,表示內部執行緒池的真實大小。
  • getActiveCount(): 此方法返回一個int數,表示當前執行任務的執行緒數。
  • getTaskCount(): 此方法返回一個long數,表示已經分配執行的任務數。
  • getCompletedTaskCount(): 此方法返回一個long數,表示已經被這個執行者執行並結束執行的任務數。
  • isShutdown(): 當 執行的 shutdown() 方法被呼叫來結束執行時,此方法返回 Boolean 值。
  • isTerminating(): 當執行者正在操作shutdown(),但是還沒結束時,此方法返回 Boolean 值。
  • isTerminated(): 當這個執行者結束執行時,此方法返回 Boolean 值。

參見

第四章,執行緒執行者:建立執行緒執行者
第七章,自定義併發類:自定義ThreadPoolExecutor類
第七章,自定義併發類:實現基於優先的執行者類