这些实现之间有什么区别?在哪种情况下应该使用一个或另一个队列?
答案 0 :(得分:7)
TransferQueue 比SynchronousQueue更通用和有用,但是它允许您灵活地决定是否使用正常 BlockingQueue语义或保证切换。在这种情况下 项目已经在队列中,呼叫转移将保证 在传输之前将处理所有现有队列项 项目
SynchronousQueue 实现使用双队列(用于等待生产者和等待的使用者)并使用a保护两个队列 单锁。 LinkedTransferQueue实现使用CAS 形成非阻塞实现的操作,即在 避免序列化瓶颈的核心。
答案 1 :(得分:1)
Hemz的答案中没有提到另外一个重要点。
摘自Alex Miller的puredanger.github.io:
BlockingQueue
表示队列的概念:
生产者可以在将项目添加到队列时阻止,直到出现 可用空间。
从队列中删除项目时,消费者可以阻止,直到 项目存在。
TransferQueue
进一步向前迈进了一步,并阻止了该销售,直到消费者(不只是添加到队列)实际消费了该项目。这个新约束在称为transfer()
的关键新方法中表达。这个名称非常具有描述性-因为阻塞发生在从一个线程到另一个线程的移交完成之前,所以您正在有效地在线程之间转移该项目(以一种在Java内存模型中正确创建事前发生关系的方式)。 / p>
实现实际上类似于BlockingQueue-但 给我们提供了实施某种形式的背压的新能力。这个 表示当生产者使用以下方式向消费者发送消息时 transfer()方法,生产者将一直处于阻塞状态,直到 邮件已耗尽。
当我们不想要时,TransferQueue可能会非常有用 生产量过高的生产者,将在队列中充斥消息, 导致内存不足错误。在这种设计中,消费者将 决定生产者生成消息的速度。
当生产者到达TransferQueue以传输消息时, 有消费者在等待消息,然后是生产者 将消息传输给消费者。
如果没有消费者在等待,那么生产者将不会直接放 消息并返回,而是它将等待任何消费者 可以使用该消息。
其他点:
还包括其他几种方法:tryTransfer()
的两种形式执行传输,但是是非阻塞的(仅在可以立即完成时才进行传输)或超时。然后有几个辅助方法hasWaitingConsumer()
和getWaitingConsumerCount()
。
TransferQueue
比SynchronousQueue
更通用,也更有用,因为它使您可以灵活地决定是使用常规BlockingQueue
语义还是有保证的移交。如果项目已在队列中,则呼叫转移将确保所有现有队列项目将在转移的项目之前得到处理。
William Scherer,Doug Lea和Michael Scott的论文对LinkedTransferQueue
算法和性能测试进行了布局,展示了它们在现有Java 5替代方案之上的改进。 LinkedTransferQueue
在不公平模式下的表现比SynchronousQueue
高3倍,在公平模式下的表现是14倍。
Doug Lea说,在能力方面,LinkedTransferQueue
实际上是ConcurrentLinkedQueue
,SynchronousQueue
(在“公平”模式下)和不受限制的LinkedBlockingQueues
的超集。通过允许您混合和匹配这些功能以及利用更高性能的实施技术,它会变得更好。