Java LinkedBlockingQueue 与 ConcurrentLinkedQueue
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1426754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
LinkedBlockingQueue vs ConcurrentLinkedQueue
提问by Adamski
My question relates to this questionasked earlier. In situations where I am using a queue for communication between producer and consumer threads would people generally recommend using LinkedBlockingQueue
or ConcurrentLinkedQueue
?
我的问题与之前提出的这个问题有关。在我使用队列在生产者和消费者线程之间进行通信的情况下,人们通常会推荐使用LinkedBlockingQueue
或ConcurrentLinkedQueue
?
What are the advantages / disadvantages of using one over the other?
使用其中一种的优点/缺点是什么?
The main difference I can see from an API perspective is that a LinkedBlockingQueue
can be optionally bounded.
我可以从 API 的角度看到的主要区别是 aLinkedBlockingQueue
可以选择有界。
采纳答案by Jon Skeet
For a producer/consumer thread, I'm not sure that ConcurrentLinkedQueue
is even a reasonable option - it doesn't implement BlockingQueue
, which is the fundamental interface for producer/consumer queues IMO. You'd have to call poll()
, wait a bit if you hadn't found anything, and then poll again etc... leading to delays when a new item comes in, and inefficiencies when it's empty (due to waking up unnecessarily from sleeps).
对于生产者/消费者线程,我不确定这ConcurrentLinkedQueue
是否是一个合理的选择 - 它没有实现BlockingQueue
,这是生产者/消费者队列 IMO 的基本接口。你必须打电话poll()
,如果你没有找到任何东西,稍等片刻,然后再次轮询等等......导致新项目进入时的延迟,以及空时效率低下(由于不必要地从睡眠中醒来) .
From the docs for BlockingQueue:
来自 BlockingQueue 的文档:
BlockingQueue
implementations are designed to be used primarily for producer-consumer queues
BlockingQueue
实现主要用于生产者-消费者队列
I know it doesn't strictlysay that only blocking queues should be used for producer-consumer queues, but even so...
我知道它并没有严格地说只应将阻塞队列用于生产者-消费者队列,但即便如此......
回答by Ovidiu Lupas
Another solution (that does not scale well) is rendezvous channels : java.util.concurrent SynchronousQueue
另一个解决方案(不能很好地扩展)是集合通道:java.util.concurrent SynchronousQueue
回答by Rahul
If your queue is non expandable and contains only one producer/consumer thread. You can use lockless queue (You don't need to lock the data access).
如果您的队列不可扩展且仅包含一个生产者/消费者线程。您可以使用无锁队列(您不需要锁定数据访问)。
回答by dcernahoschi
LinkedBlockingQueue
blocks the consumer or the producer when the queue is empty or full and the respective consumer/producer thread is put to sleep. But this blocking feature comes with a cost: every put or take operation is lock contended between the producers or consumers (if many), so in scenarios with many producers/consumers the operation might be slower.
LinkedBlockingQueue
当队列为空或已满并且相应的消费者/生产者线程进入睡眠状态时,会阻塞消费者或生产者。但是这种阻塞特性是有代价的:每一个 put 或 take 操作都会在生产者或消费者(如果很多)之间进行锁竞争,所以在有许多生产者/消费者的情况下,操作可能会更慢。
ConcurrentLinkedQueue
is not using locks, but CAS, on its put/take operations potentially reducing contention with many producer and consumer threads. But being an "wait free" data structure, ConcurrentLinkedQueue
will not block when empty, meaning that the consumer will need to deal with the take()
returning null
values by "busy waiting", for example, with the consumer thread eating up CPU.
ConcurrentLinkedQueue
没有使用锁,而是CAS,在它的 put/take 操作中可能会减少与许多生产者和消费者线程的争用。但是作为“无等待”的数据结构,ConcurrentLinkedQueue
空时不会阻塞,这意味着消费者需要通过“忙等待”来处理take()
返回null
值,例如消费者线程占用CPU。
So which one is "better" depends on the number of consumer threads, on the rate they consume/produce, etc. A benchmark is needed for each scenario.
因此,哪个“更好”取决于消费者线程的数量、他们消费/生产的速率等。每个场景都需要一个基准。
One particular use case where the ConcurrentLinkedQueue
is clearly better is when producers first produce something and finish their job by placing the work in the queue and only afterthe consumers starts to consume, knowing that they will be done when queue is empty. (here is no concurrency between producer-consumer but only between producer-producer and consumer-consumer)
一个ConcurrentLinkedQueue
明显更好的特定用例是当生产者首先生产一些东西并通过将工作放入队列来完成他们的工作时,并且只有在消费者开始消费之后,知道他们将在队列为空时完成。(这里没有生产者-消费者之间的并发,而只有生产者-生产者和消费者-消费者之间的并发)
回答by Alexandru Nedelcu
This question deserves a better answer.
这个问题值得更好的回答。
Java's ConcurrentLinkedQueue
is based on the famous algorithm by Maged M. Michael and Michael L. Scottfor non-blocking lock-freequeues.
JavaConcurrentLinkedQueue
基于Maged M. Michael 和 Michael L. Scott的著名算法,用于非阻塞无锁队列。
"Non-blocking" as a term here for a contended resource (our queue) means that regardless of what the platform's scheduler does, like interrupting a thread, or if the thread in question is simply too slow, other threads contending for the same resource will still be able to progress. If a lock is involved for example, the thread holding the lock could be interrupted and all threads waiting for that lock would be blocked. Intrinsic locks (the synchronized
keyword) in Java can also come with a severe penalty for performance - like when biased lockingis involved and you do have contention, or after the VM decides to "inflate" the lock after a spin grace period and block contending threads ... which is why in many contexts (scenarios of low/medium contention), doing compare-and-sets on atomic references can be much more efficient and this is exactly what many non-blocking data-structures are doing.
“非阻塞”在这里作为竞争资源(我们的队列)的术语意味着无论平台的调度程序做什么,例如中断线程,或者如果有问题的线程太慢,其他线程都在竞争相同的资源还是可以进步的。例如,如果涉及锁,持有该锁的线程可能会被中断,并且所有等待该锁的线程都将被阻塞。synchronized
Java 中的内在锁(关键字)也会对性能带来严重的损失——比如偏向锁涉及并且您确实有争用,或者在虚拟机决定在自旋宽限期之后“膨胀”锁并阻止竞争线程之后......这就是为什么在许多情况下(低/中争用场景),进行比较和原子引用上的 -sets 可以更有效,这正是许多非阻塞数据结构正在做的事情。
Java's ConcurrentLinkedQueue
is not only non-blocking, but it has the awesome property that the producer does not contend with the consumer. In a single producer / single consumer scenario (SPSC), this really means that there will be no contention to speak of. In a multiple producer / single consumer scenario, the consumer will not contend with the producers. This queue does have contention when multiple producers try to offer()
, but that's concurrency by definition. It's basically a general purpose and efficient non-blocking queue.
JavaConcurrentLinkedQueue
不仅是非阻塞的,而且它具有生产者不与消费者竞争的令人敬畏的特性。在单一生产者/单一消费者场景 (SPSC) 中,这真的意味着将没有争用可言。在多生产者/单消费者场景中,消费者不会与生产者竞争。当多个生产者尝试时offer()
,此队列确实存在争用,但根据定义,这是并发性。它基本上是一个通用且高效的非阻塞队列。
As for it not being a BlockingQueue
, well, blocking a thread to wait on a queue is a freakishly terrible way of designing concurrent systems. Don't. If you can't figure out how to use a ConcurrentLinkedQueue
in a consumer/producer scenario, then just switch to higher-level abstractions, like a good actor framework.
至于它不是一个BlockingQueue
,好吧,阻塞线程以在队列上等待是设计并发系统的一种非常糟糕的方式。别。如果您无法弄清楚如何ConcurrentLinkedQueue
在消费者/生产者场景中使用 a ,那么只需切换到更高级别的抽象,例如一个好的 actor 框架。