同步队列与转移队列之间的区别

2022-09-04 21:41:34

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


答案 1

正如亚历克斯·米勒在这篇文章中提到的

TransferQueue比SyncQueue更通用和有用,因为它允许您灵活地决定是使用正常的BlocklingQueue语义还是保证移交。如果项目已在队列中,则调用传输将保证在传输的项目之前处理所有现有队列项目。

同步队列实现使用双队列(用于等待的生产者和等待的消费者),并使用单个锁保护这两个队列。LinkedTransferQueue 实现使用 CAS 操作来形成非阻塞实现,这是避免序列化瓶颈的核心。


答案 2

还有一点在Hemz的回答中没有提到。

来自Alex Miller的 puredanger.github.io

BlockingQueue表示队列的概念::

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

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

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

baeldung.com

该实现实际上类似于BlockQueue - 但为我们提供了实现一种形式的背压的新能力。这意味着,当生产者使用transfer()方法向消费者发送消息时,生产者将保持阻塞状态,直到消息被使用。

当我们不希望过度生产的生产者用消息淹没队列,从而导致 OutOfMemory 错误时,TransferQueue 可能非常有用。在这种设计中,消费者将决定生产者生成消息的速度。

howtodoinjava.com

当生产者到达 TransferQueue 以传输消息并且有使用者等待获取消息时,生产者直接将消息传输到使用者。

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

其他要点:

资料来源:puredanger.github.io

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

TransferQueue它比它更通用和有用,因为它允许您灵活地决定是使用正常的语义还是有保证的交接。如果项目已在队列中,则调用传输将保证在传输的项目之前处理所有现有队列项目。SynchronousQueueBlockingQueue

William Scherer,Doug Lea和Michael Scott的一篇论文列出了算法和性能测试,展示了它们对现有Java 5替代方案的改进。 在不公平模式下的表现高出3倍,在公平模式下的表现高出14倍。LinkedTransferQueueLinkedTransferQueueSynchronousQueue

Doug Lea说,从能力上讲,实际上是的超集(在“公平”模式下),并且是无限的。通过允许您混合和匹配这些功能以及利用更高性能的实现技术,它变得更好。LinkedTransferQueueConcurrentLinkedQueueSynchronousQueueLinkedBlockingQueues


推荐