针对JavaDoc中ThreadPoolExecutor的说明不明确,无法确定直接向支持执行器的BlockingQueue
添加任务是否可以接受。然而文档中提到,调用executor.getQueue()
主要用于调试和监控。
我使用自己的BlockingQueue
构建了一个ThreadPoolExecutor
,并保留了队列的引用,以便直接向其添加任务。由于getQueue()
返回相同的队列,因此我假设getQueue()
中的警告也适用于通过我的方式获得的后台队列引用。
示例
代码的一般模式如下:
int n = ...; // number of threads
queue = new ArrayBlockingQueue<Runnable>(queueSize);
executor = new ThreadPoolExecutor(n, n, 1, TimeUnit.HOURS, queue);
executor.prestartAllCoreThreads();
// ...
while (...) {
Runnable job = ...;
queue.offer(job, 1, TimeUnit.HOURS);
}
while (jobsOutstanding.get() != 0) {
try {
Thread.sleep(...);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
executor.shutdownNow();
queue.offer()
vs executor.execute()
通常使用executor.execute()
添加任务,而我上面的例子则是在队列上阻塞而不是使用execute()
,因为如果队列已满并拒绝我的任务,它就会立即失败。我也喜欢提交作业与阻塞队列交互;这感觉更像是"纯粹的"生产者-消费者。
直接添加任务到队列的一个影响是,我必须调用prestartAllCoreThreads()
,否则没有工作线程正在运行。假设没有与执行器的其他交互,那么没有任何东西来监视队列(检查ThreadPoolExecutor
源代码可证实)。这也意味着对于直接入队操作,ThreadPoolExecutor
必须额外配置> 0个核心线程,并且不能配置为允许核心线程超时。
tl;dr
给定如下配置的ThreadPoolExecutor
:
- 核心线程数> 0
- 不允许核心线程超时
- 已预启动核心线程
- 持有指向支持执行器的
BlockingQueue
的引用
是否可以直接将任务添加到队列中,而不是调用executor.execute()
?
Related
这个问题 (生产者/消费者工作队列)类似,但没有特别涉及直接添加到队列的问题。