Java - 如何记录线程池中的指标?

Java - How to log metrics from a ThreadPool?

我在我自己的 ExecutorService 的实现中包装了一个 ThreadPoolExecutor,只是为了向它发送任何文件系统写入任务,所以他们会依次并一一处理。 (不用再骚扰这可怜的写盘头了。)

包装器可以派上用场:

最后一个功能是通过调用 logUtils.writingHeartbeat(int) 来完成的,如果 [=34] =] 自上次记录以来已经过去了时间。它在按所需时间间隔写入日志方面效果很好,但总是告诉我还有 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.
}

所以我认为问题在于您在完全 运行 提交 Runnable 之后按顺序检查队列大小。所以 Runnable 已经完全完成它的工作然后它检查队列大小这将是空的除非你用完了 innerPool 中的线程数。换句话说,队列中必须有一些东西在等待它打印出除 0 以外的任何内容。当前作业正在 运行 由线程处理,因此它不在队列中。

我同意@chubbsondubs 的观点,代码中的其他地方一定存在同步问题。

我证明一些事情的建议是:

  • 尝试记录 getTaskCountgetCompletedTaskCount。 这导致您观察到,在给定时间队列中确实只有 1 个任务。

  • 扩展 ThreadPoolExecutor 并使用 afterExecute 挂钩,而不是组合。也许你可以调查谁在同步而不应该那样。