什么时候更喜欢 LinkedBlockingQueue 而不是 ArrayBlockingQueue?

When to prefer LinkedBlockingQueue over ArrayBlockingQueue?

什么时候更喜欢 LinkedBlockingQueue 而不是 ArrayBlockingQueue

LinkedBlockingQueueArrayBlockingQueue中使用哪个数据结构当:

  1. 你想要高效的读写
  2. 应该有更少的内存占用

虽然也有类似的问题但是没有突出哪个应该优先的事实?

链接:

来自JavaDoc for ArrayBlockingQueue

A bounded blocking queue backed by an array.

强调我的

来自JavaDoc for LinkedBlockingQueue

An optionally-bounded blocking queue based on linked nodes.

强调我的

因此,如果您需要 有界 队列,您可以使用任一队列,如果您需要 无界 队列,则必须使用 LinkedBlockingQueue.

对于有界队列,您需要进行基准测试以确定哪个更好。

Boris the Spider 已经概述了 ArrayBlockingQueueLinkedBlockingQueue 之间最明显的区别 - 前者总是有界的,而后者可以是无界的。

因此,如果您需要无限阻塞队列,LinkedBlockingQueue 或用作 BlockingQueueLinkedTransferQueuejava.util.concurrent 工具箱中的最佳选择。

但是假设您需要一个有界阻塞队列。 最后,您应该根据对真实工作负载的模拟进行广泛试验来选择实施。 不过,这里有一些注释可以帮助您做出选择或解释实验结果:

  • ArrayBlockingQueue 可以使用可配置的 (on/off) 调度公平策略来创建。如果您需要公平或想避免 producer/consumer 饥饿,这很好,但它会降低吞吐量。
  • ArrayBlockingQueue 预先分配其支持数组,因此它在使用期间不分配节点,但它会立即占用相当大的内存块,如果您的内存不足,这可能是个问题支离破碎。
  • ArrayBlockingQueue 应该在性能上具有较小的可变性,因为它总体上具有较少的移动部件,它使用更简单和不太复杂的单锁算法,它在使用过程中不创建节点,它的缓存行为应该相当一致。
  • LinkedBlockingQueue 应该有更好的吞吐量,因为它对头部和尾部使用单独的锁。
  • LinkedBlockingQueue不预分配节点,这意味着它的内存占用将大致匹配它的大小,但这也意味着它会产生一些分配和释放节点的工作。
  • LinkedBlockingQueue 可能会有更糟糕的缓存行为,这可能会影响其自身的性能,但也会由于错误共享而影响其他组件的性能。

根据您的用例以及您对性能的关注程度,您可能还想看看 java.util.concurrent 之外并考虑 Disruptor (an exceptionally fast, but somewhat specialized bounded non-blocking ring buffer) or JCTools(各种具有不同的有界或无界队列保证取决于生产者和消费者的数量)。