2009-05-28 179 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); 
} 
}