我使用一个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