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

问题描述 投票:0回答:3

什么时候更喜欢

LinkedBlockingQueue
而不是
ArrayBlockingQueue

当以下情况时,在

LinkedBlockingQueue
ArrayBlockingQueue
中使用哪种数据结构:

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

虽然有类似的问题,但它并没有强调哪个应该是首选的事实?

链接:

java multithreading concurrency blockingqueue
3个回答
109
投票

蜘蛛鲍里斯已经概述了

ArrayBlockingQueue
LinkedBlockingQueue
之间最明显的区别 - 前者总是有界的,而后者可以是无界的。

因此,如果您需要无界阻塞队列,

LinkedBlockingQueue
或用作
LinkedTransferQueue
BlockingQueue
java.util.concurrent
工具箱中的最佳选择。

但是假设您需要一个有界阻塞队列。 最后,您应该根据对实际工作负载的模拟进行大量实验来选择实施方案。 尽管如此,这里有一些注释可以帮助您做出选择或解释实验结果:

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

根据您的用例以及您对性能的关心程度,您可能还想看看

java.util.concurrent
之外的内容并考虑 Disruptor (一种速度非常快,但有些专业的有界非阻塞环形缓冲区)或 JCTools (根据生产者和消费者的数量,具有不同保证的各种有界或无界队列)。


22
投票

来自 JavaDoc for

ArrayBlockingQueue

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

强调我的

来自 JavaDoc for

LinkedBlockingQueue

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

强调我的

因此,如果您需要一个有界队列,您可以使用其中一个,如果您需要一个无界队列,您必须使用

LinkedBlockingQueue

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


0
投票

虽然 ArrayBlockingQueue 总体上更简单,但我相信它对 put 和 take 操作都使用单个锁。因此,如果您使用它来传输非常频繁(例如每秒数千或数百万条消息)消息从一个线程到另一个线程,则可能会因争用而导致性能更差。

相反,我认为 LinkedBlockingQueue 使用独立的锁来进行 put 和 take。因此,如果只有一个线程放入,另一个线程取出,则争用可能会较少。但是,如果您有多个线程放入或多个线程取出,则可能会出现更多争用,因为每个锁定操作都会比 ArrayBockingQueue 的等效操作长一点。

结论:如果您使用它频繁地将消息从单个源线程传输到单个目标线程,那么 LinkedBlockingQueue 可能会更好,因为它可能具有更少的争用。否则 ArrayBlockingQueue 可能会稍微快一些。

如果有疑问,您必须针对您的特定用例进行实际测试。但是,除非您尝试每秒发送数百万条消息,否则您可能不会注意到任何显着差异 - 在大多数情况下,两者都同样有效:)

© www.soinside.com 2019 - 2024. All rights reserved.