我将 ThreadPoolExecutor 包装在我自己的 ExecutorService 的实现中,只是为了向它发送任何文件系统编写任务,所以它们将按顺序排列并逐个处理一。 (不需要骚扰这个可怜的磁盘写头。)
包装器派上用场:
最后一个功能是通过调用 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.
}
答案 0 :(得分:1)
我同意@chubbsondubs的意见,代码中的其他地方一定存在同步问题。
我建议证明一些事情是:
尝试记录getTaskCount
和getCompletedTaskCount
。
这导致您观察到,在给定时间内队列中确实只有1个任务。
而不是组合,扩展ThreadPoolExecutor并使用afterExecute
钩子。也许你可以调查那个不应该同步的人。
答案 1 :(得分:0)
所以我认为问题是你在完全运行提交的Runnable后依次检查队列大小。所以Runnable完全完成了它的工作,然后检查队列大小,除非你已经用尽了innerPool中的线程数,否则它将是空的。换句话说,队列中必须有一些东西等待它打印出除0之外的任何东西。当前作业由一个线程运行,因此它不在队列中。