有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

记录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.
}

共 (2) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

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

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

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

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