什么时候更喜欢 LinkedBlockingQueue 而不是 ArrayBlockingQueue?
When to prefer LinkedBlockingQueue over ArrayBlockingQueue?
什么时候更喜欢 LinkedBlockingQueue
而不是 ArrayBlockingQueue
?
在LinkedBlockingQueue
和ArrayBlockingQueue
中使用哪个数据结构当:
- 你想要高效的读写
- 应该有更少的内存占用
虽然也有类似的问题但是没有突出哪个应该优先的事实?
链接:
- Java: ArrayBlockingQueue vs. LinkedBlockingQueue
- What is the Difference between ArrayBlockingQueue and LinkedBlockingQueue
来自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 已经概述了 ArrayBlockingQueue
和 LinkedBlockingQueue
之间最明显的区别 - 前者总是有界的,而后者可以是无界的。
因此,如果您需要无限阻塞队列,LinkedBlockingQueue
或用作 BlockingQueue
的 LinkedTransferQueue
是 java.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(各种具有不同的有界或无界队列保证取决于生产者和消费者的数量)。
什么时候更喜欢 LinkedBlockingQueue
而不是 ArrayBlockingQueue
?
在LinkedBlockingQueue
和ArrayBlockingQueue
中使用哪个数据结构当:
- 你想要高效的读写
- 应该有更少的内存占用
虽然也有类似的问题但是没有突出哪个应该优先的事实?
链接:
- Java: ArrayBlockingQueue vs. LinkedBlockingQueue
- What is the Difference between ArrayBlockingQueue and LinkedBlockingQueue
来自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 已经概述了 ArrayBlockingQueue
和 LinkedBlockingQueue
之间最明显的区别 - 前者总是有界的,而后者可以是无界的。
因此,如果您需要无限阻塞队列,LinkedBlockingQueue
或用作 BlockingQueue
的 LinkedTransferQueue
是 java.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(各种具有不同的有界或无界队列保证取决于生产者和消费者的数量)。