我使用一個ExecutorService發射了任務,調度需要通過特定任務的標準進行分組任務:如何使用ExecutorService跟蹤任務執行統計信息?
Task[type=a]
Task[type=b]
Task[type=a]
...
週期性我要輸出的平均時間長度,每個任務了(由type
分組)以及統計信息,如平均值/中位數和標準差。
當然,這需要非常快,理想情況下不應導致各個線程在報告統計信息時進行同步。這樣做的好架構是什麼?
我使用一個ExecutorService發射了任務,調度需要通過特定任務的標準進行分組任務:如何使用ExecutorService跟蹤任務執行統計信息?
Task[type=a]
Task[type=b]
Task[type=a]
...
週期性我要輸出的平均時間長度,每個任務了(由type
分組)以及統計信息,如平均值/中位數和標準差。
當然,這需要非常快,理想情況下不應導致各個線程在報告統計信息時進行同步。這樣做的好架構是什麼?
ThreadPoolExecutor提供了beforeExecute和afterExecute您可以覆蓋的方法。您可以使用這些工具將您的統計信息記錄在單個(您的ExecutorService的成員變量)ConcurrentHashMap中,並將其記錄爲您的任務的某個唯一標識符,並存儲類型,開始時間和結束時間。
當你準備好看他們時,從ConcurrentHashMap
計算統計。
子類Thread Pool Executor並跟蹤執行事件:
值得一提的是,該方法是由工作線程執行該任務調用,所以你需要確保執行跟蹤代碼的線程安全。
另外,您將收到的Runnables很可能不是您的Runnables,而是包裹在FutureTasks中。
我相信其他兩個答案都是正確的,但也許有點太複雜了(雖然我的答案,雖然簡單,但可能不是很爲他們的高性能。
爲什麼不直接使用原子變量保持跟蹤你的狀態?例如運行的任務數量,總執行時間(除以總數,你得到的平均執行時間)。將這些變量傳遞給每個任務的Runnable。除非你的任務非常短暫,否則我不認爲鎖定一個Atomic變量會影響你
另一種方式是使用包裝/裝飾器模式
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);
}
}
我應該注意;我知道_在哪裏,我會從這些方法中調用這些方法,我希望得到關於我應該如何累積數據的建議。 – 2009-05-28 21:36:50
每種任務類型是否都有自己的Runnable? – Gandalf 2009-05-28 21:37:00