记录Java如何从线程池记录度量?
我将一个ThreadPoolExecutor封装在自己的ExecutorService实现中,只是为了将任何文件系统写入任务发送给它,这样它们就会被依次逐个处理。(无需骚扰这个糟糕的磁盘写入头。)
包装器有以下优点:
- 允许我将这个线程池作为Guice Singleton注入几乎所有我需要的地方
- 实时告诉我还有多少工作要做
最后一个特性是通过调用logUtils来完成的。writingHeartbeat(int)记录一条消息,如果自上次记录以来已经过了“足够”的时间,那么队列中还有多少作业。它在以所需的时间间隔写入日志方面非常有效,但总是告诉我还有0个文件要写。考虑到执行时间,这听起来很可疑
我做错了什么
@Singleton
public class WritersThreadPool implements ExecutorService {
private final ThreadPoolExecutor innerPool;
private final LogUtils logUtils;
@Inject
public WritersThreadPool(LogUtils logUtils) {
innerPool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
this.logUtils = logUtils;
}
@Override
public Future<?> submit(final Runnable r) {
return innerPool.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
r.run();
logUtils.writingHeartbeat(innerPool.getQueue().size());
return null;
}
});
}
(...) // Other implemented methods with no special behavior.
}
# 1 楼答案
因此,我认为问题在于,在完全运行要提交的Runnable之后,您正在按顺序检查队列大小。所以Runnable已经完全完成了它的工作,然后它会检查队列大小,除非您耗尽了innerPool中的线程数,否则队列大小将为空。换句话说,队列中必须有东西等待它打印出除0以外的任何内容。当前作业正在由线程运行,因此它不在队列中
# 2 楼答案
我同意@chubbsondubs的观点,代码中的其他地方肯定存在同步问题
我的建议是证明一些事情:
尝试记录
getTaskCount
和getCompletedTaskCount
。 这导致了您的观察,即在给定的时间内,队列中确实只有一个任务扩展ThreadPoolExecutor并使用
afterExecute
钩子,而不是组合。也许你可以调查谁在同步,但不应该这样