优雅地为 ExecutorServices 实现队列长度指示器
为什么,哦,为什么java.util.concurrent
不为其ExecutorService
提供队列长度指标?最近我发现自己在做这样的事情:
Why, oh why doesn't java.util.concurrent
provide a queue length indicators for its ExecutorService
s? Recently I found myself doing something like this:
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
}
}
哪个工作正常,但是...我认为这确实应该作为 ExecutorService
的一部分来实现.从实际队列中携带一个 分离 的计数器是愚蠢且容易出错的,计数器应该指示其长度(让我想起了 C 数组).但是,ExecutorService
是通过静态工厂方法获得的,所以没有办法简单地扩展其他优秀的单线程执行器并添加队列计数器.那我该怎么办:
Which works ok, but... I think this really should be implemented as a part of the ExecutorService
. It's dumb and error prone to carry around a counter separated from the actual queue, whose length the counter is supposed to indicate (reminds me of C arrays). But, ExecutorService
s are obtained via static factory methods, so there's no way to simply extend the otherwise excellent single thread executor and add a queue counter. So what should I do:
- 重新发明已经在 JDK 中实现的东西?
- 其他巧妙的解决方案?
推荐答案
还有更直接的方法:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newSingleThreadExecutor();
// add jobs
// ...
int size = executor.getQueue().size();
虽然您可能会考虑不使用 Executor 的便捷创建方法,而是直接创建 executor 以摆脱强制转换,从而确保 executor 实际上始终是 ThreadPoolExecutor
,即使 Executors.newSingleThreadExecutor
的实现有一天会改变.
Although you might consider not to use the convenience create methods of Executor, but rather create the executor directly to get rid of the cast and thus be sure that the executor will always actually be a ThreadPoolExecutor
, even if the implementation of Executors.newSingleThreadExecutor
would change some day.
ThreadPoolExecutor executor = new ThreadPoolExecutor( 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>() );
这是直接从 JDK 1.6 中的 Executors.newSingleThreadExecutor
复制而来的.传递给构造函数的 LinkedBlockingQueue
实际上就是您将从 getQueue
得到的对象.
This is directly copied from Executors.newSingleThreadExecutor
in JDK 1.6. The LinkedBlockingQueue
that is passed to the constructor is actually the very object that you will get back from getQueue
.
相关文章