2009-05-28 79 views
8

我使用一個ExecutorService發射了任務,調度需要通過特定任務的標準進行分組任務:如何使用ExecutorService跟蹤任務執行統計信息?

Task[type=a] 
Task[type=b] 
Task[type=a] 
... 

週期性我要輸出的平均時間長度,每個任務了(由type分組)以及統計信息,如平均值/中位數和標準差。

當然,這需要非常快,理想情況下不應導致各個線程在報告統計信息時進行同步。這樣做的好架構是什麼?

+0

我應該注意;我知道_在哪裏,我會從這些方法中調用這些方法,我希望得到關於我應該如何累積數據的建議。 – 2009-05-28 21:36:50

+0

每種任務類型是否都有自己的Runnable? – Gandalf 2009-05-28 21:37:00

回答

9

ThreadPoolExecutor提供了beforeExecuteafterExecute您可以覆蓋的方法。您可以使用這些工具將您的統計信息記錄在單個(您的ExecutorService的成員變量)ConcurrentHashMap中,並將其記錄爲您的任務的某個唯一標識符,並存儲類型,開始時間和結束時間。

當你準備好看他們時,從ConcurrentHashMap計算統計。

4

子類Thread Pool Executor並跟蹤執行事件:

值得一提的是,該方法是由工作線程執行該任務調用,所以你需要確保執行跟蹤代碼的線程安全。

另外,您將收到的Runnables很可能不是您的Runnables,而是包裹在FutureTasks中。

1

我相信其他兩個答案都是正確的,但也許有點太複雜了(雖然我的答案,雖然簡單,但可能不是很爲他們的高性能。

爲什麼不直接使用原子變量保持跟蹤你的狀態?例如運行的任務數量,總執行時間(除以總數,你得到的平均執行時間)。將這些變量傳遞給每個任務的Runnable。除非你的任務非常短暫,否則我不認爲鎖定一個Atomic變量會影響你

2

另一種方式是使用包裝/裝飾器模式

public class Job implements Runnable { 
private Runnable _task; 
private Statistics _statistics; 

public Job(Runnable task, Statistics statistics) { 
    this._task = task; 
} 

public void run() { 
    long s = System.currentTimeMillis(); 
    _task.run(); 
    long e = System.currentTimeMillis(); 

    long executionTime = e - s; 
    _statistics.updateStatistics(executionTime); 
} 
}