Java 我应该在什么时候通过LinkedBlockingQueue使用SynchronousQueue
有什么区别?什么时候我应该对容量为1的Java 我应该在什么时候通过LinkedBlockingQueue使用SynchronousQueue,java,concurrency,blockingqueue,Java,Concurrency,Blockingqueue,有什么区别?什么时候我应该对容量为1的LinkedBlockingQueue使用SynchronousQueue SynchronousQueue更像是一个切换,而LinkedBlockingQueue只允许一个元素。不同之处在于,对SynchronousQueue的put()调用在出现相应的take()调用之前不会返回,但对于大小为1的LinkedBlockingQueue,put()调用(对空队列)将立即返回 我不能说我自己曾经直接使用过SynchronousQueue,但它是用于Execu
LinkedBlockingQueue
使用SynchronousQueue
SynchronousQueue更像是一个切换,而LinkedBlockingQueue只允许一个元素。不同之处在于,对SynchronousQueue的put()调用在出现相应的take()调用之前不会返回,但对于大小为1的LinkedBlockingQueue,put()调用(对空队列)将立即返回
我不能说我自己曾经直接使用过SynchronousQueue,但它是用于Executors.newCachedThreadPool()
方法的默认阻塞队列。它本质上是一个BlockingQueue实现,适用于您不需要队列(您不想维护任何挂起的数据)的情况
就我所知,上面的代码也做同样的事情
不,代码完全不同
同步。需要有服务员才能成功提供服务。LBQ将保留该商品,即使没有服务员,报价也将立即结束
SyncQ对于任务切换非常有用。假设您有一个带有挂起任务的列表和3个可用线程在队列中等待,尝试使用列表的1/4执行offer()
,如果不接受,线程可以自己运行任务。[如果您想知道为什么是1/4而不是1/3,那么最后1/4应该由当前线程处理]
考虑尝试将任务交给工作人员,如果没有可用的任务,您可以选择自己执行任务(或引发异常)。相反,使用LBQ时,将任务留在队列中并不保证任何执行
注意:消费者和发布者的情况相同,即发布者可能会阻止并等待消费者,但在
提供
或轮询
返回后,它会确保任务/元素得到处理。使用SynchronousQueue的一个原因是为了提高应用程序性能。如果必须在线程之间进行切换,则需要一些同步对象。如果您能够满足使用它所需的条件,SynchronousQueue是我找到的最快的同步对象。其他人也同意。请参阅:SynchronousQueue以类似的方式工作,主要区别如下:
1) SynchronousQueue的大小为0
2) 如果take()方法能够在同一时刻从队列中提取元素,则put()方法将仅插入元素,即,如果使用者take()调用将花费一些时间来使用某个元素,则无法插入该元素
SynchronousQueue-仅当有人在该时刻收到它时才插入。[只是尝试用(可能)更清晰的词来表达它。]
我非常清楚地相信这些国家的情况:
poll()
将返回null
BlockingQueue
检索时队列为空,则操作将一直阻塞,直到插入新元素为止。此外,如果在插入阻塞队列时队列已满,则操作将阻塞,直到从队列中删除元素并为新队列留出空间为止。但是请注意,在SynchronousQueue
中,由于在另一个线程上发生相反的操作(插入和删除操作彼此相反),操作被阻止因此,与阻塞队列
不同,阻塞取决于操作的存在,而不是元素的存在或不存在
peek()
始终返回null
(再次检查),并且迭代器()
返回一个空迭代器,其中hasNext()
始终返回false
。(). 但是,请注意,poll()
方法整洁地检索并删除此队列的头,如果另一个线程当前正在使元素可用,并且如果不存在这样的线程,则返回null
。()最后,请注意,
SynchronousQueue
和LinkedBlockingQueue
类都实现了BlockingQueue
接口。同步队列基本上用于切换目的。它们没有任何线程,put操作被阻塞,直到其他线程执行get操作
如果我们想在两个线程之间安全地共享一个变量,我们可以将该变量放入同步队列中,让另一个线程从队列中获取它
源代码示例
ExecutorService executor=Executors.newFixedThreadPool(2);
SynchronousQueue=新的SynchronousQueue();
可运行生产者=()->{
整数producedElement=ThreadLocalRandom
.current()
.nextInt();
试一试{
队列。put(生产删除);
}捕获(Int)
new SynchronousQueue()
new LinkedBlockingQueue(1)
ExecutorService executor = Executors.newFixedThreadPool(2);
SynchronousQueue<Integer> queue = new SynchronousQueue<>();
Runnable producer = () -> {
Integer producedElement = ThreadLocalRandom
.current()
.nextInt();
try {
queue.put(producedElement);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
};
Runnable consumer = () -> {
try {
Integer consumedElement = queue.take();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
};
executor.execute(producer);
executor.execute(consumer);
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
executor.shutdown();
assertEquals(queue.size(), 0);