为什么ArrayBlockingQueue被称为有界队列而LinkedBlockingQueue被称为无界阻塞队列?

时间:2012-08-06 14:49:51

标签: java java.util.concurrent

据我所知,链表和数组都可以无限制地增长,或者我错了吗?但是当我经历documentation in the Executor Service时,我看到了这一点:

  

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

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

这是为ArrayBlockingQueue写的:

  

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

5 个答案:

答案 0 :(得分:10)

为什么你认为ArrayBlockingQueue可以不受限制地增长?来自own documentation

  

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

换句话说,一旦它变满了,它已经满了 - 它不会增长。

你是否有机会对ArrayList感到困惑 - 这也是一个数组的支持,但是根据需要扩展它?

  

当LinkedBlockingQueue具有已定义的容量时,Unbounded Queue属性是否会更改?

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

  

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

答案 1 :(得分:4)

javadoc for LinkedBlockingQueue说:

  

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

     

可选的容量绑定构造函数参数用作方法   防止过多的队列扩展。容量,如果没有说明,是   等于Integer.MAX_VALUE。

javadoc of ArrayBlockingQueue说:

  

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

     

这是一个经典的“有界缓冲区”,其中包含固定大小的数组   生产者插入并由消费者提取的元素。一旦   创造,容量不能增加

因此,链接的阻塞队列可以是无限的,而ArrayBlockingQueue总是有界限的。

答案 2 :(得分:3)

  

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

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

  

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

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

答案 3 :(得分:3)

来自ArrayBlockingQueue

的文档广告
  

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

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

答案 4 :(得分:0)

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

    /** 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元素。所以我认为没有完美无界的队列......