9

据我所知,链表和数组都可以无限增长还是我错了?但是当我浏览了 Executor Service 中的文档时,我看到了:

无界队列。当所有 corePoolSize 线程都忙时,使用无界队列(例如没有预定义容量的 LinkedBlockingQueue)将导致新任务在队列中等待。因此,不会创建超过 corePoolSize 个线程。(因此 maximumPoolSize 的值没有任何影响。)

那么当具有定义的容量时,Unbounded Queue属性会发生变化吗?LinkedBlockingQueue

这写的是ArrayBlockingQueue

有界队列。当与有限的 maximumPoolSizes 一起使用时,有界队列(例如 ArrayBlockingQueue)有助于防止资源耗尽,但可能更难以调整和控制。队列大小和最大池大小可以相互权衡:使用大队列和小池可以最大限度地减少 CPU 使用率、操作系统资源和上下文切换开销,但可能会导致人为地降低吞吐量。如果任务经常阻塞(例如,如果它们受 I/O 限制),系统可能能够为比您允许的更多线程安排时间。使用小队列通常需要更大的池大小,这会使 CPU 更忙,但可能会遇到不可接受的调度开销,这也会降低吞吐量。

4

5 回答 5

14

为什么你认为一个ArrayBlockingQueue可以无限增长?从它自己的文档中

这是一个经典的“有界缓冲区”,其中一个固定大小的数组保存由生产者插入并由消费者提取的元素。一旦创建,容量就无法增加。尝试将元素放入完整队列将导致操作阻塞;尝试从空队列中获取元素同样会阻塞。

换句话说,一旦它满了,它就满了——它不会增长。

您是否对 an 感到困惑ArrayList- 它也由数组支持,但根据需要扩展它?

那么当 LinkedBlockingQueue 具有定义的容量时,Unbounded Queue 属性是否会发生变化?

是的,因此它在其Javadocs中被描述为“可选有界” 。此外,文档指出(强调我的):

可选的容量绑定构造函数参数用作防止过度队列扩展的一种方式。容量(如果未指定)等于 Integer.MAX_VALUE。链接节点在每次插入时动态创建,除非这会使队列超过容量

于 2012-08-06T14:51:39.850 回答
4

LinkedBlockingQueue的javadoc说:

基于链接节点的可选有界阻塞队列。[...]

可选的容量绑定构造函数参数用作防止过度队列扩展的一种方式。容量(如果未指定)等于 Integer.MAX_VALUE。

ArrayBlockingQueue的javadoc说:

由数组支持的有界阻塞队列。[...]

这是一个经典的“有界缓冲区”,其中一个固定大小的数组保存由生产者插入并由消费者提取的元素。一经创建,容量无法增加

因此,LinkedBlockingQueue 可以是有界或无界的,而 ArrayBlockingQueue 始终是有界的。

于 2012-08-06T14:55:10.817 回答
3

据我所知,链表和数组都可以无限增长,或者我错了

一个无限大小的链表。数组具有固定大小。ArrayList 包装一个数组并在需要更大的数组时替换它。

当 LinkedBlockingQueue 具有定义的容量时,Unbounded Queue 属性也会发生变化

当 LinkedBlockingQueue 有最大容量时,它是有界的,但默认情况下不使用这种方式。

于 2012-08-06T14:52:50.027 回答
3

来自ArrayBlockingQueue的文档

由数组支持的有界阻塞队列。此队列对元素进行 FIFO(先进先出)排序。队列的头部是在队列中时间最长的元素。队列的尾部是在队列中时间最短的元素。新元素被插入到队列的尾部,队列检索操作获取队列头部的元素。

如果你注意到 ArrayBlockingQueue 的所有构造函数都占用了一个容量,因为这个类被设计为有界的。做出这个选择是因为如果您想要一个并发队列,您可能不想要调整 ArrayList 大小所带来的开销。因此,如果您想要一个无界队列 LinkedBlockingQueue 是一个更好的选择,因为它不涉及此开销。

于 2012-08-06T14:55:00.617 回答
1

其他答案非常正确!我提供另一种解释方式。好吧,我也对通过的“未绑定和绑定”一词感到困惑。你可以看看自爆的源代码。

    /** The queued items */
final Object[] items;

/** items index for next take, poll, peek or remove */
int takeIndex;

/** items index for next put, offer, or add */
int putIndex;

/** Number of elements in the queue */
int count;

从源代码中,我们可以看到数组是final的,所以我们不能调整数组的大小。如果使用 LinkedBlockingQueue,我们总是可以添加更多元素......并且在源代码中,下一个引用不是最终的。注意,理论上,LinkedBlockingQueue 不是无界的。因为它只能存储 MAX_INTEGER 减去 8 个元素。从javadoc,无界队列是PriorityBlockingQueue。但 PriorityBlockingQueue 也只能存储 MAX_INTEGER -8 个元素。所以我认为没有完美的无界队列......

于 2018-02-03T06:34:29.730 回答