您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java條件隊列是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java條件隊列是什么”吧!
關于條件隊列,你能說些什么?
條件隊列是一個容器,它承載著一組等待“先驗條件”成真的線程。
先驗條件這個詞文縐縐的,用白話講就是你做一件事的前提條件。在代碼里經常表現為你調用的方法能夠執行的前提條件。舉個例子,對于BlockingQueue你要調用put()方法,那么這個put方法能被成功調用的前提是這個blockingQueue不滿。對于已滿的情況,在同步的世界里,你可以拋異常、你可以返回一個特殊的自定義的值(在函數式編程里你可以做得更好)。在并發的世界里,如果能夠block住并等到隊列不滿的時候再繼續執行是更好的設計。“條件隊列”就是用于這種“等待、通知、再運行”機制里的一個關鍵組件。
上面提到等待、通知時,你是不是馬上想到了耳熟能詳的sychronized關鍵字?因為在synchronized里,我們經常使用wati(), notify(), notifyAll()嘛。如果你直接想到object那也挺厲害的。
先驗條件往往與對象的狀態關聯在一起,因為體現到代碼上這些條件最終都是基于某些“對象屬性”進行的布爾運算的結果,用這個結果來決定個先驗條件是否成立。在并發的世界里,對這些對象屬性必須同步才能避免多線程下因競爭而導致的問題,這就需要一個鎖把這些先驗條件用到的狀態同步起來,所以就有了下面這樣的邏輯:先驗條件 --> 狀態 --> 鎖。為了檢驗一個條件,我們必須先持有鎖。
回到上面blockingQueue的例子,我們先拿到這個隊列的鎖、再檢查隊列是否已滿。如果隊列已滿,我們就不能繼續執行put,需要block住,然后等候隊列不滿的通知。如何實現呢?調用wait()釋放鎖,等候條件成真后的通知notify,然后再繼續執行。有可能得到條件變化為真的通知,但是拿到cpu時間槽要執行的時候,條件又false了,所以wait要寫在while里,這算是個定式。
其實,講到這里后面已經默默的使用到了condition queue。當你調用wait的時候,這個線程就進到了條件隊列。而當有其它線程notify的時候,實際上就是通知條件隊列里的線程(先驗)條件發生了變化,讓這些線程有機會重新去檢查這些條件并繼續運行。在這里,我們可以體會下調用wait()都隱式的對應到等待一個先驗條件(條件謂詞)為真,而調用notify/All都隱式的對應到一個先驗條件發生了變化。
大家一般都知道sycnhronized與monitor(內置鎖)緊密聯系。進入同步代碼塊之前,你必須擁有monitor。實際上,條件隊列也是與鎖緊密聯系的(甚至就是‘同一個’對象)。就內置條件隊列來說,比較不好的一面是:調用wait()把線程放入這個內部條件隊列意味著因為等待不同“先驗條件”的線程都在同一隊列中,就是說不同的先驗條件共享同一個內部條件隊列。這樣在notifyAll進行喚醒的時候就并不高效了。
而Condition接口,可以幫助我們針對不同的先驗條件創建不同的條件隊列,這樣就可以只喚醒與之對應的線程了。從鎖與條件隊列的關系你應該可以猜到,Lock接口提供了創建條件隊列的方法。
public interface Lock { Condition newCondition(); ... ...
下面是Condition的接口定義,可以看到就如Lock是內部鎖的泛化、顯示化,而Condition就是內部條件隊列的泛化、顯示化。
感謝各位的閱讀,以上就是“Java條件隊列是什么”的內容了,經過本文的學習后,相信大家對Java條件隊列是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。