我什么时候应该使用SynchronousQueue

Ant*_*ton 54 java concurrency blockingqueue

new SynchronousQueue()
new LinkedBlockingQueue(1)
Run Code Online (Sandbox Code Playgroud)

有什么不同?什么时候应该使用SynchronousQueueLinkedBlockingQueue产能1?

jta*_*orn 50

SynchronousQueue更像是一种切换,而LinkedBlockingQueue只允许一个元素.不同之处在于,对于SynchronousQueue的put()调用在相应的take()调用之前不会返回,但是对于大小为1的LinkedBlockingQueue,put()调用(到空队列)将立即返回.

我不能说我曾经直接使用过SynchronousQueue,但它是用于这些Executors.newCachedThreadPool()方法的默认BlockingQueue .它本质上是BlockingQueue的实现,当你做的不是真的想要一个队列(你不想保持任何未决的数据).

  • @Umar当多个线程为队列生成对象的速度快于消费者可以使用和处理它们时 - 队列的大小可能会过度增长.SynchronousQueue有助于控制通信,而无需生成器中的任何特定代码.在现实生活中,它类似于一个人回答别人提出的问题的会议.将SynchronousQueue视为一种秘书. (11认同)
  • 如果您将其他单线程操作分解为多个阶段,并将这些阶段与在它们之间传递的工作项一起流水线化,并在其自己的线程中运行每个阶段,您将从重叠中获得并发性。在这种情况下,“扫描CSV”和“插入记录”是两个阶段,它们可以同时进行以饱和数据库插入。 (2认同)

bes*_*sss 9

据我所知,上面的代码做了同样的事情.

不,代码完全不一样.

Sync.Q. 要求服务员提供成功.LBQ将保留该项目,即使没有服务员也会立即完成优惠.

SyncQ对于任务切换很有用.想象一下,你有一个列表w /待处理任务和3个线程可用等待队列,尝试offer()使用列表的1/4,如果不接受线程可以自己运行任务.[最后1/4应该由当前线程处理,如果你想知道为什么1/4而不是1/3]

考虑将任务交给工人,如果没有可用,您可以选择自己执行任务(或抛出异常).相反w/LBQ,将任务留在队列中并不能保证任何执行.

注意:具有消费者和发布者的情况是相同的,即发布者可以阻止并等待消费者但是在发布offerpoll返回之后,它确保要处理任务/元素.


小智 6

使用SynchronousQueue的一个原因是提高应用程序性能.如果必须在线程之间进行切换,则需要一些同步对象.如果您能满足其使用所需的条件,SynchronousQueue是我找到的最快的同步对象.其他人同意.请参阅:BlockingQueue的实现:SynchronousQueue和LinkedBlockingQueue之间有什么区别


ani*_*nir 5

[只是试图用(可能)更清晰的语言表达出来。]

我相信SynchronousQueueAPI 文档说明得非常清楚:

  1. 阻塞队列,其中每个插入操作必须等待另一个线程的相应删除操作,反之亦然。
  2. 同步队列没有任何内部容量,甚至没有容量 1。您无法查看同步队列,因为只有当您尝试删除元素时才会出现该元素;你不能插入一个元素(使用任何方法),除非另一个线程试图删除它;你无法迭代,因为没有什么可迭代的。
  3. 队列头是第一个排队插入线程尝试添加到队列中的元素;如果没有这样的排队线程,则没有可用于删除的元素poll()并将返回null

BlockingQueueAPI 文档

  1. 队列还支持在检索元素时等待队列变为非空的操作,以及在存储元素时等待队列中的空间变为可用的操作。

因此,差异是显而易见的,而且有些微妙,尤其是下面的第三点:

  1. 如果从 检索时队列为空BlockingQueue,则操作会阻塞,直到插入新元素。另外,如果在插入时队列已满BlockingQueue,则操作将阻塞,直到该元素从队列中删除并为新队列腾出空间。但请注意,在 中SynchronousQueue,as 操作会因另一个线程上发生的相反操作(插入和删除彼此相反)而被阻止。因此,与 不同的是BlockingQueue,阻塞取决于操作的存在,而不是元素的存在或不存在
  2. 由于阻塞取决于相反操作的存在,因此元素永远不会真正插入队列中。这就是为什么第二点:“同步队列没有任何内部容量,甚至没有一个容量。
  3. 因此,peek()always 返回null(再次检查API 文档)并iterator()返回一个空迭代器,其中hasNext()always 返回false。(API 文档)。但是,请注意,poll()如果另一个线程当前正在使元素可用,并且不存在这样的线程,则该方法会巧妙地检索并删除该队列的头部,则返回null。(API文档

最后,有一点需要注意的是,类SynchronousQueueLinkedBlockingQueue类都实现BlockingQueue接口。