我的问题与之前提出的this question有关。在我使用队列在生产者线程和消费者线程之间进行通信的情况下,人们通常会推荐使用LinkedBlockingQueue或ConcurrentLinkedQueue
使用一种比另一种有什么优点/缺点?
从API的角度来看,我能看到的主要区别是,LinkedBlockingQueue可以是可选的绑定。
发布于 2009-09-15 12:11:40
对于生产者/消费者线程,我甚至不确定ConcurrentLinkedQueue是否是一个合理的选择--它没有实现BlockingQueue,后者是生产者/消费者队列的基本接口。你必须调用poll(),如果你没有找到任何东西,请稍等片刻,然后再次轮询,等等……这会导致新项目进入时的延迟,以及空项目时的效率低下(由于不必要地从睡眠中醒来)。
在BlockingQueue的文档中:
BlockingQueue实现主要用于生产者-消费者队列
我知道严格来说并不是说只有阻塞队列才能用于生产者-消费者队列,但即便如此...
发布于 2014-06-27 04:43:29
这个问题应该有一个更好的答案。
Java的ConcurrentLinkedQueue基于著名的用于non-blocking lock-free队列的algorithm by Maged M. Michael and Michael L. Scott。
“非阻塞”在这里指的是争用资源(我们的队列),意思是不管平台的调度器做什么,比如中断线程,或者如果有问题的线程太慢,争用相同资源的其他线程仍然能够进行。例如,如果涉及锁,持有该锁的线程可能会被中断,并且等待该锁的所有线程都将被阻塞。Java语言中的内部锁( synchronized关键字)也会带来严重的性能损失--比如当涉及到biased locking而您确实有争用时,或者在VM决定在旋转宽限期后“膨胀”锁并阻塞争用线程之后……这就是为什么在许多上下文中(低/中争用的场景),对原子引用进行比较和设置可能更有效,这正是许多非阻塞数据结构正在做的事情。
Java的ConcurrentLinkedQueue不仅是非阻塞的,而且具有生产者不与消费者竞争的强大特性。在单一生产者/单一消费者场景(SPSC)中,这实际上意味着没有争用可言。在多生产者/单消费者场景中,消费者不会与生产者竞争。当多个生产者尝试offer()时,此队列确实存在争用,但根据定义,这是并发。它基本上是一个通用的、高效的非阻塞队列。
至于它不是BlockingQueue,那么,阻塞线程在队列中等待是设计并发系统的一种非常糟糕的方式。如果你不知道如何在消费者/生产者场景中使用ConcurrentLinkedQueue,那么就切换到更高级别的抽象,比如一个好的角色框架。
发布于 2014-02-13 05:21:20
当队列为空或已满时,LinkedBlockingQueue会阻塞消费者或生产者,并将相应的消费者/生产者线程置于睡眠状态。但是这种阻塞特性是有代价的:每个put或take操作都是生产者或消费者(如果有很多)之间的锁争用,因此在有许多生产者/消费者的情况下,操作可能会更慢。
ConcurrentLinkedQueue在其添加/轮询操作中使用的不是锁,而是CAS,这可能会减少与许多生产者和消费者线程的争用。但是作为一种“等待自由”的数据结构,ConcurrentLinkedQueue在为空时不会阻塞,这意味着消费者将需要通过“忙碌等待”来处理返回CPU值的poll(),例如,消费者线程将占用null。
因此,哪一个“更好”取决于消费者线程的数量,取决于它们消耗/产生的速率,等等。每个场景都需要一个基准。
ConcurrentLinkedQueue明显更好的一个特定用例是,当生产者第一次通过将工作放在队列中来完成他们的工作时,只有在之后,消费者才开始消费,因为他们知道当queue为空时他们就会完成。(这里没有生产者-消费者之间的并发,只有生产者-生产者和消费者-消费者之间的并发)
https://stackoverflow.com/questions/1426754
复制相似问题