同步队列与传输队列之间的区别



这两种实现有什么区别?在哪些情况下应该一个使用?

正如Alex Miller在这篇文章中提到的

TransferQueue比SyncQueue更通用和有用,因为它允许您灵活地决定是否使用normal。 阻塞队列语义或有保证的交接。在以下情况下 项目已经在队列中,呼叫转接将保证 所有现有的队列项目将在传输之前处理 项目。

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

Hemz 的回答中没有提到更重要的一点。

来自亚历克斯米勒的 puredanger.github.io:

BlockingQueue表达了队列的概念,该队列:

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

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

TransferQueue更进一步,阻止放置,直到项目实际被消费者使用(而不仅仅是添加到队列中(。这个新约束在称为 transfer() 的关键新方法中表示。这个名称是非常描述性的 – 因为阻塞发生在从一个线程到另一个线程的交接完成之前,所以您实际上是在线程之间传输项目(以一种在 Java 内存模型中正确创建发生之前关系的方式(。

从 baeldung.com

该实现实际上类似于 BlockingQueue – 但是赋予我们实施某种形式的背压的新能力。这意味着,当生产者使用在 transfer(( 方法中,生产者将保持阻塞状态,直到消息被消耗。

当我们不想要 过度生产的生产者,将用消息淹没队列, 导致内存不足错误。在这样的设计中,消费者将 决定生产者生成消息的速度。

从 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的超集。通过允许您混合和匹配这些功能以及利用更高性能的实现技术,它变得更好。

最新更新