Java中的SynchronousQueue隊列詳解
簡介
SynchronousQueue是BlockingQueue的一種,所以SynchronousQueue是線程安全的。
SynchronousQueue和其他的BlockingQueue不同的是SynchronousQueue的capacity是0。
即SynchronousQueue不存儲任何元素。
也就是說SynchronousQueue的每一次insert操作,必須等待其他線性的remove操作。
而每一個remove操作也必須等待其他線程的insert操作。
這種特性可以讓我們想起了Exchanger。和Exchanger不同的是,使用SynchronousQueue可以在兩個線程中傳遞同一個對象。
一個線程放對象,另外一個線程取對象。
舉例說明
我們舉一個多線程中傳遞對象的例子。
還是舉生產(chǎn)者消費者的例子,在生產(chǎn)者中我們創(chuàng)建一個對象,在消費者中我們?nèi)〕鲞@個對象。
先看一下用CountDownLatch該怎么做:
@Test public void useCountdownLatch() throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(2); AtomicReference<Object> atomicReference= new AtomicReference<>(); CountDownLatch countDownLatch = new CountDownLatch(1); Runnable producer = () -> { Object object=new Object(); atomicReference.set(object); log.info("produced {}",object); countDownLatch.countDown(); }; Runnable consumer = () -> { try { countDownLatch.await(); Object object = atomicReference.get(); log.info("consumed {}",object); } catch (InterruptedException ex) { log.error(ex.getMessage(),ex); } }; executor.submit(producer); executor.submit(consumer); executor.awaitTermination(50000, TimeUnit.MILLISECONDS); executor.shutdown(); }
上例中,我們使用AtomicReference來存儲要傳遞的對象,并且定義了一個型號量為1的CountDownLatch。
在producer中,我們存儲對象,并且countDown。
在consumer中,我們await,然后取出對象。
輸出結(jié)果:
[pool-1-thread-1] INFO com.flydean.SynchronousQueueUsage - produced java.lang.Object@683d1b4b
[pool-1-thread-2] INFO com.flydean.SynchronousQueueUsage - consumed java.lang.Object@683d1b4b
可以看到傳入和輸出了同一個對象。
上面的例子我們也可以用SynchronousQueue來改寫:
@Test public void useSynchronousQueue() throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(2); SynchronousQueue<Object> synchronousQueue=new SynchronousQueue<>(); Runnable producer = () -> { Object object=new Object(); try { synchronousQueue.put(object); } catch (InterruptedException ex) { log.error(ex.getMessage(),ex); } log.info("produced {}",object); }; Runnable consumer = () -> { try { Object object = synchronousQueue.take(); log.info("consumed {}",object); } catch (InterruptedException ex) { log.error(ex.getMessage(),ex); } }; executor.submit(producer); executor.submit(consumer); executor.awaitTermination(50000, TimeUnit.MILLISECONDS); executor.shutdown(); }
上面的例子中,如果我們使用synchronousQueue,則可以不用手動同步,也不需要額外的存儲。
總結(jié)
如果我們需要在代碼中用到這種線程中傳遞對象的情況,那么使用synchronousQueue吧。
到此這篇關(guān)于Java中的SynchronousQueue隊列詳解的文章就介紹到這了,更多相關(guān)SynchronousQueue隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot 在普通類型注入Service或mapper
這篇文章主要介紹了Springboot 在普通類型注入Service或mapper,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11springboot多數(shù)據(jù)源使用@Qualifier自動注入無效的解決
這篇文章主要介紹了springboot多數(shù)據(jù)源使用@Qualifier自動注入無效的解決,具有很好的參考價值,希望對大家有所幫助。也希望大家多多支持腳本之家2021-11-11SpringBoot Import及自定義裝配實現(xiàn)方法解析
這篇文章主要介紹了SpringBoot Import及自定義裝配實現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-08-08Spring Boot中的WebSocketMessageBrokerConfigurer接口使用
在SpringBoot中,我們可以使用 WebSocketMessageBrokerConfigurer接口來配置WebSocket消息代理,以實現(xiàn)實時通信,具有一定的參考價值,感興趣的可以了解一下2023-11-11詳解Java的Hibernate框架中的Interceptor和Collection
這篇文章主要介紹了Java的Hibernate框架中的Interceptor和Collection,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2016-01-01