SynchronousQueue与TransferQueue之间的区别

时间:2014-11-30 21:53:40

标签: java concurrency queue producer-consumer

这些实现之间有什么区别?在哪种情况下应该使用一个或另一个队列?

2 个答案:

答案 0 :(得分:7)

正如this post by Alex Miller

中所述
  

TransferQueue 比SynchronousQueue更通用和有用,但是它允许您灵活地决定是否使用正常   BlockingQueue语义或保证切换。在这种情况下   项目已经在队列中,呼叫转移将保证   在传输之前将处理所有现有队列项   项目

     

SynchronousQueue 实现使用双队列(用于等待生产者和等待的使用者)并使用a保护两个队列   单锁。 LinkedTransferQueue实现使用CAS   形成非阻塞实现的操作,即在   避免序列化瓶颈的核心。

答案 1 :(得分:1)

Hemz的答案中没有提到另外一个重要点。

摘自Alex Miller的puredanger.github.io

BlockingQueue表示队列的概念:

  1. 生产者可以在将项目添加到队列时阻止,直到出现 可用空间。

  2. 从队列中删除项目时,消费者可以阻止,直到 项目存在。

TransferQueue进一步向前迈进了一步,并阻止了该销售,直到消费者不只是添加到队列实际消费了该项目。这个新约束在称为transfer()的关键新方法中表达。这个名称非常具有描述性-因为阻塞发生在从一个线程到另一个线程的移交完成之前,所以您正在有效地在线程之间转移该项目(以一种在Java内存模型中正确创建事前发生关系的方式)。 / p>

来自baeldung.com

实现实际上类似于BlockingQueue-但 给我们提供了实施某种形式的背压的新能力。这个 表示当生产者使用以下方式向消费者发送消息时 transfer()方法,生产者将一直处于阻塞状态,直到 邮件已耗尽。

当我们不想要时,TransferQueue可能会非常有用 生产量过高的生产者,将在队列中充斥消息, 导致内存不足错误。在这种设计中,消费者将 决定生产者生成消息的速度。

来自howtodoinjava.com

当生产者到达TransferQueue以传输消息时, 有消费者在等待消息,然后是生产者 将消息传输给消费者。

如果没有消费者在等待,那么生产者将不会直接放 消息并返回,而是它将等待任何消费者 可以使用该消息。

其他点:

来源:puredanger.github.io

还包括其他几种方法:tryTransfer()的两种形式执行传输,但是是非阻塞的(仅在可以立即完成时才进行传输)或超时。然后有几个辅助方法hasWaitingConsumer()getWaitingConsumerCount()

TransferQueueSynchronousQueue更通用,也更有用,因为它使您可以灵活地决定是使用常规BlockingQueue语义还是有保证的移交。如果项目已在队列中,则呼叫转移将确保所有现有队列项目将在转移的项目之前得到处理。

William Scherer,Doug Lea和Michael Scott的论文对LinkedTransferQueue算法和性能测试进行了布局,展示了它们在现有Java 5替代方案之上的改进。 LinkedTransferQueue在不公平模式下的表现比SynchronousQueue高3倍,在公平模式下的表现是14倍。

Doug Lea说,在能力方面,LinkedTransferQueue实际上是ConcurrentLinkedQueueSynchronousQueue(在“公平”模式下)和不受限制的LinkedBlockingQueues的超集。通过允许您混合和匹配这些功能以及利用更高性能的实施技术,它会变得更好。