为什么 Executors 创建 Executor 使用 LinkedBlockingQueue 而不是 ConcurrentLinkedQueue
Why Executors create Executor use LinkedBlockingQueue instead of ConcurrentLinkedQueue
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
使用 LinkedBlockingQueue,但是 ConcurrentLinkedQueue 是否应该更高效,即无阻塞和无锁?
如果你将Runnable对象提交到队列中,而没有运行个线程来消费这些任务,它们当然不会被执行。当队列变空时,池必须阻塞并等待更多任务。因此,为了实现此行为,我们在与池交互时使用 BlockingQueue。
答案很简单:ConcurrentLinkedQueue
不是 BlockingQueue
,但 LinkedBlockingQueue
是。 ThreadPoolExecutor
constructors 期望 BlockingQueue
s,因此 Executors
也使用 BlockingQueue
的其他实现创建实例,如 SynchronousQueue
或 ArrayBlokingQueue
(取决于您在 Executors
中调用的工厂方法)。
所以,更普遍的问题是:为什么 BlockingQueue
而不是简单的 Queue
。答案也很简单:BlockingQueue
接口有更多有用的方法。例如,一个方法判断是否可以在不违反容量限制的情况下将元素插入队列(并且不抛出异常,检查 BlockingQueue.offer()
)。或者,如果队列没有元素(同样具有定时 poll()
而不是定时版本 take()
),则某些方法会阻塞。因此,如果您检查 ThreadPoolExecutor 的实现,您会发现它调用了 Queue
接口中缺少的这些方便的方法。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
使用 LinkedBlockingQueue,但是 ConcurrentLinkedQueue 是否应该更高效,即无阻塞和无锁?
如果你将Runnable对象提交到队列中,而没有运行个线程来消费这些任务,它们当然不会被执行。当队列变空时,池必须阻塞并等待更多任务。因此,为了实现此行为,我们在与池交互时使用 BlockingQueue。
答案很简单:ConcurrentLinkedQueue
不是 BlockingQueue
,但 LinkedBlockingQueue
是。 ThreadPoolExecutor
constructors 期望 BlockingQueue
s,因此 Executors
也使用 BlockingQueue
的其他实现创建实例,如 SynchronousQueue
或 ArrayBlokingQueue
(取决于您在 Executors
中调用的工厂方法)。
所以,更普遍的问题是:为什么 BlockingQueue
而不是简单的 Queue
。答案也很简单:BlockingQueue
接口有更多有用的方法。例如,一个方法判断是否可以在不违反容量限制的情况下将元素插入队列(并且不抛出异常,检查 BlockingQueue.offer()
)。或者,如果队列没有元素(同样具有定时 poll()
而不是定时版本 take()
),则某些方法会阻塞。因此,如果您检查 ThreadPoolExecutor 的实现,您会发现它调用了 Queue
接口中缺少的这些方便的方法。