Ant*_*ton 54 java concurrency blockingqueue
new SynchronousQueue()
new LinkedBlockingQueue(1)
Run Code Online (Sandbox Code Playgroud)
有什么不同?什么时候应该使用SynchronousQueue
对LinkedBlockingQueue
产能1?
jta*_*orn 50
SynchronousQueue更像是一种切换,而LinkedBlockingQueue只允许一个元素.不同之处在于,对于SynchronousQueue的put()调用在相应的take()调用之前不会返回,但是对于大小为1的LinkedBlockingQueue,put()调用(到空队列)将立即返回.
我不能说我曾经直接使用过SynchronousQueue,但它是用于这些Executors.newCachedThreadPool()
方法的默认BlockingQueue .它本质上是BlockingQueue的实现,当你做的不是真的想要一个队列(你不想保持任何未决的数据).
据我所知,上面的代码做了同样的事情.
不,代码完全不一样.
Sync.Q. 要求服务员提供成功.LBQ将保留该项目,即使没有服务员也会立即完成优惠.
SyncQ对于任务切换很有用.想象一下,你有一个列表w /待处理任务和3个线程可用等待队列,尝试offer()
使用列表的1/4,如果不接受线程可以自己运行任务.[最后1/4应该由当前线程处理,如果你想知道为什么1/4而不是1/3]
考虑将任务交给工人,如果没有可用,您可以选择自己执行任务(或抛出异常).相反w/LBQ,将任务留在队列中并不能保证任何执行.
注意:具有消费者和发布者的情况是相同的,即发布者可以阻止并等待消费者但是在发布offer
或poll
返回之后,它确保要处理任务/元素.
小智 6
使用SynchronousQueue的一个原因是提高应用程序性能.如果必须在线程之间进行切换,则需要一些同步对象.如果您能满足其使用所需的条件,SynchronousQueue是我找到的最快的同步对象.其他人同意.请参阅:BlockingQueue的实现:SynchronousQueue和LinkedBlockingQueue之间有什么区别
[只是试图用(可能)更清晰的语言表达出来。]
我相信SynchronousQueue
API 文档说明得非常清楚:
- 阻塞队列,其中每个插入操作必须等待另一个线程的相应删除操作,反之亦然。
- 同步队列没有任何内部容量,甚至没有容量 1。您无法查看同步队列,因为只有当您尝试删除元素时才会出现该元素;你不能插入一个元素(使用任何方法),除非另一个线程试图删除它;你无法迭代,因为没有什么可迭代的。
- 队列头是第一个排队插入线程尝试添加到队列中的元素;如果没有这样的排队线程,则没有可用于删除的元素
poll()
并将返回null
。
- 队列还支持在检索元素时等待队列变为非空的操作,以及在存储元素时等待队列中的空间变为可用的操作。
因此,差异是显而易见的,而且有些微妙,尤其是下面的第三点:
BlockingQueue
,则操作会阻塞,直到插入新元素。另外,如果在插入时队列已满BlockingQueue
,则操作将阻塞,直到该元素从队列中删除并为新队列腾出空间。但请注意,在 中SynchronousQueue
,as 操作会因另一个线程上发生的相反操作(插入和删除彼此相反)而被阻止。因此,与 不同的是BlockingQueue
,阻塞取决于操作的存在,而不是元素的存在或不存在。peek()
always 返回null
(再次检查API 文档)并iterator()
返回一个空迭代器,其中hasNext()
always 返回false
。(API 文档)。但是,请注意,poll()
如果另一个线程当前正在使元素可用,并且不存在这样的线程,则该方法会巧妙地检索并删除该队列的头部,则返回null
。(API文档)最后,有一点需要注意的是,类SynchronousQueue
和LinkedBlockingQueue
类都实现BlockingQueue
接口。