Ada*_*ski 104 java queue concurrency multithreading data-structures
我的问题涉及前面提到的这个问题.在我使用队列进行生产者和消费者线程之间的通信的情况下,人们通常会建议使用LinkedBlockingQueue
或ConcurrentLinkedQueue
?
使用一个优于另一个的优点/缺点是什么?
从API的角度来看,我可以看到的主要区别是a LinkedBlockingQueue
可以选择性地限制.
Jon*_*eet 103
对于生产者/消费者线程,我不确定这ConcurrentLinkedQueue
是否是一个合理的选择 - 它没有实现BlockingQueue
,这是生产者/消费者队列IMO的基本接口.poll()
如果你没有找到任何东西,你必须打电话,稍等一下,然后再次轮询等......导致新项目进入时的延迟,以及空闲时的低效率(由于睡眠不必要地唤醒) .
来自BlockingQueue的文档:
BlockingQueue
实现主要用于生产者 - 消费者队列
我知道并不严格地说只有阻塞队列应该用于生产者 - 消费者队列,但即便如此......
Ale*_*lcu 63
这个问题值得一个更好的答案.
Java ConcurrentLinkedQueue
是基于Maged M. Michael和Michael L. Scott着名的非阻塞无锁队列算法.
"非阻塞"作为争用资源(我们的队列)的术语,意味着无论平台的调度程序做什么,如中断线程,或者有问题的线程太慢,其他线程争用相同的资源仍然可以进步.例如,如果涉及锁定,则可以中断持有锁定的线程,并且将阻止等待该锁定的所有线程.synchronized
Java中的内部锁(关键字)也可能会对性能造成严重损失 - 例如,当涉及到偏向锁定并且确实存在争用时,或者在VM决定在自旋宽限期后"膨胀"锁定并阻止竞争线程之后...这就是为什么在许多情况下(低/中等争用的场景),对原子引用进行比较和设置可以更加有效,这正是许多非阻塞数据结构正在做的事情.
Java ConcurrentLinkedQueue
不仅是非阻塞的,而且具有生产者不与消费者竞争的强大属性.在单一的生产者/单一消费者场景(SPSC)中,这实际上意味着没有争论可言.在多生产者/单一消费者场景中,消费者不会与生产者竞争.当多个生成器尝试时offer()
,此队列确实存在争用,但这是根据定义的并发性.它基本上是一个通用且高效的非阻塞队列.
至于它不是一个BlockingQueue
好的,阻塞线程在队列上等待是设计并发系统的一种非常糟糕的方式.别.如果您无法弄清楚如何ConcurrentLinkedQueue
在消费者/生产者场景中使用a ,那么只需切换到更高级别的抽象,就像一个好的actor框架.
dce*_*chi 28
LinkedBlockingQueue
当队列为空或满并且相应的消费者/生产者线程进入休眠状态时阻止消费者或生产者.但是这种阻塞功能带来了成本:每个put或take操作都是生产者或消费者之间的争用(如果很多),因此在许多生产者/消费者的情况下,操作可能会更慢.
ConcurrentLinkedQueue
在其put/take操作中没有使用锁而是使用CAS可能会减少许多生产者和消费者线程的争用.但是作为一个"等待免费"的数据结构,ConcurrentLinkedQueue
在空时不会阻塞,这意味着消费者需要通过"忙等待" 来处理take()
返回null
值,例如,消费者线程占用CPU.
那么哪个"更好"取决于消费者线程的数量,它们消耗/生产的速率等.每个方案都需要一个基准.
ConcurrentLinkedQueue
明显更好的一个特殊用例是当生产者首先生产某些东西并通过将工作放在队列中并且仅在消费者开始消费之后完成他们的工作时,知道他们将在队列为空时完成.(这里不是生产者 - 消费者之间的并发,而只是生产者 - 生产者和消费者 - 消费者之间的并发)