优雅地将队列长度指示符实现到ExecutorServices

Joo*_*kka 33 java queue concurrency executorservice executor

为什么,为什么不java.util.concurrent提供其ExecutorServices 的队列长度指标?最近我发现自己做了这样的事情:

ExecutorService queue = Executors.newSingleThreadExecutor();
AtomicInteger queueLength = new AtomicInteger();
...

public void addTaskToQueue(Runnable runnable) {
    if (queueLength.get() < MAX_QUEUE_LENGTH) {
        queueLength.incrementAndGet(); // Increment queue when submitting task.
        queue.submit(new Runnable() {
            public void run() {
                runnable.run();
                queueLength.decrementAndGet(); // Decrement queue when task done.
            }
        });
    } else {
        // Trigger error: too long queue
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个工作正常,但......我认为这应该作为一部分实现ExecutorService.这是一个愚蠢的错误,容易携带一个与实际队列分开的计数器,计数器应该指示它的长度(让我想起C数组).但是,ExecutorServices是通过静态工厂方法获得的,因此无法简单地扩展优秀的单线程执行器并添加队列计数器.所以我该怎么做:

  1. 重新发明已经在JDK中实现的东西?
  2. 其他聪明的解决方案?

x4u*_*x4u 57

还有一种更直接的方式:

ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newSingleThreadExecutor();
// add jobs
// ...
int size = executor.getQueue().size();
Run Code Online (Sandbox Code Playgroud)

虽然您可能考虑不使用Executor的方便创建方法,而是直接创建执行程序以摆脱强制转换,从而确保执行程序总是实际上是一个ThreadPoolExecutor,即使实现Executors.newSingleThreadExecutor将在某一天发生变化.

ThreadPoolExecutor executor = new ThreadPoolExecutor( 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>() );
Run Code Online (Sandbox Code Playgroud)

这是从Executors.newSingleThreadExecutorJDK 1.6中直接复制的.该LinkedBlockingQueue传递给构造实际上是非常的对象,你会得到回来getQueue.

  • 具有讽刺意味的是,在我试过的一台机器上,我得到了一个`FinalizableDelegatedExecutorService`而不是一个`ThreadPoolExecutor`. (12认同)
  • 查看[源代码](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/Executors.java#Executors.newSingleThreadExecutor%28 %29),我不知道如何将 `ExecutorService` 直接转换为 `ThreadPoolExecutor`。我也像往常一样不断收到`ClassCastException`。 (3认同)
  • 实际上,我会自己使用演员表,因为 ThreadPoolExecutor 是一个公共类,因此在某种程度上也是 newSingleThreadExecutor 的公共 API 的一部分。我认为 newSingleThreadExecutor 创建的对象不再是 ThreadPoolExecutor 的可能性比 newSingleThreadExecutor 中构造函数调用的参数有一天可能会改变的可能性更小,即使用一些更有效或更精确的实现或其他什么。 (2认同)