Java中的SynchronousQueue示例–生产者使用者解决方案
SynchronousQueue是BlockingQueue的一種特殊類型,其中每個(gè)插入操作必須等待另一個(gè)線程進(jìn)行相應(yīng)的刪除操作,反之亦然。 當(dāng)您在SynchronousQueue上調(diào)用put()方法時(shí),它將阻塞,直到有另一個(gè)線程將該元素從Queue中取出為止。 同樣,如果一個(gè)線程嘗試刪除一個(gè)元素并且當(dāng)前不存在任何元素,則該線程將被阻塞,直到另一個(gè)線程將一個(gè)元素放入隊(duì)列中為止。 您可以將SynchronousQueue與運(yùn)行奧運(yùn)火炬的運(yùn)動(dòng)員( 線程 )相關(guān)聯(lián),使他們運(yùn)行火炬(需要傳遞對(duì)象)并將其傳遞給在另一端等待的其他運(yùn)動(dòng)員。 如果您注意該名稱,您還將了解到它被命名為SynchronousQueue是有原因的,它將數(shù)據(jù)同步傳遞到其他線程。 它等待對(duì)方獲取數(shù)據(jù),而不僅僅是放入數(shù)據(jù)并返回(異步操作)。 如果您熟悉CSP和Ada,那么您就會(huì)知道同步隊(duì)列類似于集合通道。 它們非常適合切換設(shè)計(jì),在該設(shè)計(jì)中,在一個(gè)線程中運(yùn)行的對(duì)象必須與在另一個(gè)線程中運(yùn)行的對(duì)象同步,以便向其傳遞一些信息,事件或任務(wù)。 在早期的多線程教程中,我們學(xué)習(xí)了如何使用wait and notify和BlockingQueue解決生產(chǎn)者消費(fèi)者問(wèn)題,在本教程中,我們將學(xué)習(xí)如何使用同步隊(duì)列來(lái)實(shí)現(xiàn)生產(chǎn)者消費(fèi)者設(shè)計(jì)模式 。 此類還支持用于訂購(gòu)等待的生產(chǎn)者和使用者線程的可選公平性策略。 默認(rèn)情況下,不保證此排序。 但是,將Fairness屬性設(shè)置為true構(gòu)造的隊(duì)列將按FIFO順序授予線程訪問(wèn)權(quán)限。
正如我之前說(shuō)過(guò)的,沒(méi)有什么比生產(chǎn)者使用者問(wèn)題更好地理解任何編程語(yǔ)言中的線程間通信了。 在生產(chǎn)者使用者問(wèn)題中,一個(gè)線程充當(dāng)產(chǎn)生事件或任務(wù)的生產(chǎn)者,而另一個(gè)線程充當(dāng)使用者。 共享緩沖區(qū)用于將數(shù)據(jù)從生產(chǎn)者傳輸?shù)较M(fèi)者。 解決生產(chǎn)者使用者問(wèn)題的困難在于邊緣情況,例如,如果緩沖區(qū)已滿,生產(chǎn)者必須等待,如果緩沖區(qū)為空,使用者線程必須等待。 后來(lái)一個(gè)很容易,因?yàn)樽枞?duì)列不僅提供緩沖區(qū)來(lái)存儲(chǔ)數(shù)據(jù),而且還提供流控制來(lái)阻塞線程,如果緩沖區(qū)已滿,則調(diào)用put()方法(PRODUCER),如果阻塞為空,則阻塞線程將調(diào)用take()方法(CONSUMER) 。 在本教程中,我們將使用SynchronousQueue(一種零容量的特殊并發(fā)集合)解決相同的問(wèn)題。
在下面的示例中,我們有兩個(gè)線程,分別名為PRODUCER和CONSUMER(您應(yīng)始終命名線程,這是編寫(xiě)并發(fā)應(yīng)用程序的最佳實(shí)踐之一)。 第一線程,發(fā)布板球得分,第二線程正在消耗它。 板球比分不過(guò)是一個(gè)String對(duì)象。 如果您按原樣運(yùn)行程序,則不會(huì)發(fā)現(xiàn)任何不同。 為了了解SynchronousQueue的工作原理以及如何解決生產(chǎn)者使用者問(wèn)題 ,您需要在Eclipse中調(diào)試該程序,或者只是通過(guò)注釋consumer.start()來(lái)啟動(dòng)生產(chǎn)者線程。 如果使用者線程未運(yùn)行,則生產(chǎn)者將在以下位置阻塞
隊(duì)列。 put(event); 通話,您將不會(huì)看到[PRODUCER]發(fā)布的活動(dòng):四個(gè)。 發(fā)生這種情況是由于 SynchronousQueue,它確保線程插入數(shù)據(jù)將一直阻塞,直到有線程刪除該數(shù)據(jù)為止,反之亦然。 您可以通過(guò)注釋生產(chǎn)者來(lái)測(cè)試代碼的另一部分。 開(kāi)始(); 并且僅啟動(dòng)使用者線程。
如果您仔細(xì)發(fā)送了輸出,那么您會(huì)注意到事件的順序是相反的。 似乎[CONSUMER]線程正在消耗數(shù)據(jù),甚至在[PRODUCER]線程產(chǎn)生數(shù)據(jù)之前。 發(fā)生這種情況是因?yàn)槟J(rèn)情況下,SynchronousQueue不保證任何順序,但是它具有公平性策略,如果將其設(shè)置為true,則可以按FIFO順序訪問(wèn)線程。 您可以通過(guò)將true傳遞給SynchronousQueue的重載構(gòu)造函數(shù) (即新的SynchronousQueue(boolean fair))來(lái)啟用此公平性策略。
這是Java中此特殊阻塞隊(duì)列的一些重要屬性。 將數(shù)據(jù)從一個(gè)線程同步傳輸?shù)搅硪粋€(gè)線程非常有用。 它沒(méi)有任何容量,只有在另一端有線程時(shí)才阻塞。
這就是Java中的SynchronousQueue 。 我們已經(jīng)看到了此特殊并發(fā)集合的某些特殊屬性,并學(xué)習(xí)了如何使用Java中的SynchronousQueue解決經(jīng)典的生產(chǎn)者使用者問(wèn)題。 順便說(shuō)一下,隊(duì)列有點(diǎn)令人困惑,因?yàn)樗鼪](méi)有任何能力容納您的元素。 在有一個(gè)線程正在調(diào)用take()操作之前,對(duì)put()操作的調(diào)用不會(huì)完成。 最好是線程之間共享對(duì)象的集合點(diǎn)。 換句話說(shuō),它是一個(gè)實(shí)用程序,可以在Java中的兩個(gè)線程之間同步共享數(shù)據(jù),這可能是更安全的wait和notify方法的替代方法。
翻譯自: https://www.javacodegeeks.com/2014/06/synchronousqueue-example-in-java-producer-consumer-solution.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Java中的SynchronousQueue示例–生产者使用者解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 电脑卡成狗怎么做如何让电脑变卡
- 下一篇: 如何在JavaServer Pages中