java.util.concurrent.locks.Condition文档说明
【1】Condition接口文檔描述
1.Condition類把Object監視器方法(wait,nofify, notifyAll)分解為不同對象,通過與Lock實現類的合并使用,Condition可以產生每個object都有多個等待集的效果。在Lock實現類替代synchronized方法或語句塊的地方,Condition可以替換Object監視器方法。
2.Conditions(也稱為條件隊列或條件變量),為一個線程提供了掛起執行(等待)的方法,直到另一個線程通知它某些狀態條件可能為真。
3.因為對共享狀態信息的訪問發生在不同線程,該共享信息必須被保護,因此某種形式的鎖與condition條件相關聯。等待條件提供的關鍵屬性是它(條件-condition)可以原子性釋放關聯的鎖并掛起當前線程,就像Object.wait() 方法那樣。
4.condition-條件實例本質上是綁定到鎖Lock上的。要獲取特定Lock實例的條件對象,使用newCondition() 方法;
5.舉個例子(這個例子非常經典-類似消息隊列),假設我們有一個支持put和take 方法的有界緩沖區。若嘗試對空緩存區執行take操作,則線程阻塞直到緩沖區有元素;若嘗試對滿緩存區執行put操作,則線程阻塞直到緩存區有可用空間。 我們想要把 執行put方法和task方法阻塞的線程放在單獨的等待集合中,以便我們可以使用優化,當緩存區中元素或空間可用時, 僅通知一個線程。
這可以通過使用兩個 Condition-條件實例來實現,如下(這段代碼非常重要):
class BoundedBuffer { // 有界緩沖區 final Lock lock = new ReentrantLock();// 可重入鎖final Condition notFull = lock.newCondition(); // 不為滿的條件final Condition notEmpty = lock.newCondition(); // 不為空的條件final Object[] items = new Object[100];int putptr, takeptr, count;// 插入元素 public void put(Object x) throws InterruptedException {lock.lock();// 獲取鎖 try {while (count == items.length)// 當緩沖區滿,則自旋式阻塞notFull.await();// 等待 items[putptr] = x;// 不滿,則添加元素到緩沖區 if (++putptr == items.length) putptr = 0;++count;notEmpty.signal();// 喚醒在非空條件上阻塞的線程} finally {lock.unlock();// 解鎖}}// 獲取元素 public Object take() throws InterruptedException {lock.lock();// 獲取鎖 try {while (count == 0)notEmpty.await();// 若緩存區空,則非空條件阻塞 Object x = items[takeptr];if (++takeptr == items.length) takeptr = 0;--count;notFull.signal();// 喚醒非滿條件return x;} finally {lock.unlock();// 解鎖}}}(java.util.concurrent.ArrayBlockingQueue實現了上述例子,無需自己寫代碼實現)
6.Condition實現類可以提供不同于Object監視器方法的行為和語義,如保證通知順序,執行通知時無需持有鎖。如果一個Condition實現類提供了這些專門語義,則需要記錄這些語義。
7.注意到:
- Condition實例也僅僅是普通對象,所以可以作為 synchronized方法或語句塊的目標對象,也可以調用Condition對象的監視器wait() 和 notify方法。獲取Condition實例的監視器鎖,或使用監視器方法(wait,notify,notifyAll),與獲取condition相關的Lock鎖或使用其wait或signal方法沒有任何關系。墻裂建議為了避免混淆,不要在把 Conditoin實例作為 synchronized的目標對象,除非在它們自己的實現中。
8.Condition實現類注意事項:
在等待條件時,通常允許發生虛假喚醒,作為對底層平臺語義的讓步。
這對大多數應用程序來說沒有影響,因為condition-條件應該始終在循環中等待,以測試等待的狀態謂詞(變量是否為真)。
Conditon實現類可以自由移除虛假喚醒的可能性,但墻裂建議程序員始終假設它可能發生,因此始終在循環中等待;
9.3種形式的條件等待(可中斷,不可中斷,超時)在一些平臺的實現難易程度和性能特征有所不同。特別地,可能很難提供這些特性并維護特定語義,如順序保證。此外,中斷一個線程的實際掛起的能力在所有平臺并不總是可行的;
10.因此,Condition實現類不需要為以上3種形式的等待精確定義同樣的保證和語義。也不需要支持對線程實際掛起的中斷。
11.一個Condition實現類需要記錄每個wait方法提供的語義和保證,當Condition實現類支持線程掛起時的中斷,則它必須遵守本接口定義的中斷語義。
12.中斷通常意味著取消,并且中斷檢測不常發生,所以Condition實現類傾向于響應中斷而不是方法正常返回。即使證明中斷發生在另一動作解除線程阻塞之后發生,也是如此。Condition實現類應該記錄這些行為。
【2】Condition方法
【2.1】void await() throws InterruptedException
1.該方法導致當前線程等待,直到收到信號或被中斷。
2.與此Condition關聯的鎖被自動釋放,且當前線程無法被線程調度器調度(禁用),并處于休眠狀態直到以下4種情況之一發生:
- 情況1,其他線程調用此condition的信號方法(signal),并且當前線程恰好被選擇為要被喚醒的線程 ;
- 情況2 ,其他線程調用此condition的signalAll方法;
- 情況3 , 其他線程中斷了當前線程,(當Condition實現類支持線程掛起時的中斷);
- 情況4, 發生虛假喚醒(?);
3.在所有情況下,在await() 方法從當前線程返回之前,當前線程都必須重新獲取與condition關聯的鎖。當線程返回時,能夠保證它持有鎖。
4.如果當前線程:
在該方法入口設置了中斷狀態,或等待時被中斷(且condition實現類支持線程掛起時被中斷),
則線程將拋出InterruptedException-中斷異常,且當前線程的中斷狀態被清空。
對于第一種情況,在釋放鎖之前是否進行中斷測試沒有規定。
5.Condition實現類注意事項:
在本方法被調用時,假設當前線程持有了condition對象關聯的鎖。
這取決于condition實現類確定是否是這種情況,如果不是,如何響應。通常,會拋出異常(如IllegalMonitorStateException-非法監視器狀態異常),且condition實現類會記錄該事實。
6.在響應信號過程中,condition實現類傾向于響應中斷而不是方法正常返回。在那種情況下,condition實現類必須保證信號被重定向到其他等待線程(即,sinal發給其他線程以喚醒),如果有的話 。
7.拋出異常:
InterruptedException-中斷異常,當當前線程被中斷(當condition實現類支持線程掛起時中斷)
【2.2】void awaitUninterruptibly()
1.導致當前線程等待,直到被發出信號。
2.與此contition對象關聯的鎖被自動釋放,當前線程無法被線程調度器調度(禁用), 并休眠直到以下3種情況之一發生;
- 情況1, 其他線程調用了該condition對象的 signal() 方法,且當前線程被選為要喚醒的線程;
- 情況2,其他線程調用了 該condition對象的 signalAll() 方法;
- 情況3,發生 虛假喚醒(?);
3.在所有情況下,在awaitUninterruptibly() 方法從當前線程返回之前,當前線程都必須重新獲取與condition關聯的鎖。當線程返回時,能夠保證它持有鎖。
4.若在該方法入口設置了當前線程的中斷狀態,或等待時被中斷(且condition實現類支持線程掛起時被中斷),該線程會繼續等待直到接收到信號(不會中斷)。當線程最終從該方法返回時,它的中斷狀態仍然被設置。
5.Condition實現類注意事項:
在本方法被調用時,假設當前線程持有了condition對象關聯的鎖。
這取決于condition實現類確定是否是這種情況,如果不是,如何響應。通常,會拋出異常(如IllegalMonitorStateException-非法監視器狀態異常),且condition實現類會記錄該事實。
【2.3】long awaitNanos(long nanosTimeout) throws InterruptedException
1.導致當前線程等待直到接收到信號,或被中斷,或經過給定的等待時間。
2.與此contition對象關聯的鎖被自動釋放,當前線程無法被線程調度器調度(禁用), 并休眠直到以下5種情況之一發生;
- 情況1, 其他線程調用了該condition對象的 signal() 方法,且當前線程被選為要喚醒的線程;
- 情況2,其他線程調用了 該condition對象的 signalAll() 方法;
- 情況3,其他線程中斷了當前線程,(當Condition實現類支持線程掛起時的中斷);
- 情況4,經過給定的等待時間;
- 情況5,虛假喚醒;
3.在所有情況下,在該方法從當前線程返回之前,當前線程都必須重新獲取與condition關聯的鎖。當線程返回時,能夠保證它持有鎖。
4.若在該方法入口設置了當前線程的中斷狀態,或等待時被中斷(且condition實現類支持線程掛起時被中斷),則線程將拋出InterruptedException-中斷異常,且當前線程的中斷狀態被清空。
對于第一種情況,在釋放鎖之前是否進行中斷測試沒有規定。
5.該方法根據給定的超時納秒數返回剩余等待納秒數的估計值。若超時,則該值小于或等于0.
該值可以用于確定在等待返回但等待條件不滿足的情況下是否重新等待以及重新等待多長時間。典型用法如下:
boolean aMethod(long timeout, TimeUnit unit) {long nanos = unit.toNanos(timeout);lock.lock();try {while (!conditionBeingWaitedFor()) {if (nanos <= 0L)return false;nanos = theCondition.awaitNanos(nanos);}// ...} finally {lock.unlock();}}設計說明:該方法需要一個納秒參數,以避免報告剩余時間時出現截斷錯誤。這樣的精度丟失將使程序員難以確保系統上的總等待時間不會短于重新等待時的指定值。
6.condition實現類注意事項:
在本方法被調用時,假設當前線程持有了condition對象關聯的鎖。
這取決于condition實現類確定是否是這種情況,如果不是,如何響應。通常,會拋出異常(如IllegalMonitorStateException-非法監視器狀態異常),且condition實現類會記錄該事實。
7.在響應信號過程中,condition實現類傾向于響應中斷而不是方法正常返回或者超過給定等待時間。在任何情況下,condition實現類必須保證信號被重定向到其他等待線程(即,sinal發給其他線程以喚醒),如果有的話 。
8.參數:
- nanosTimeout, 最大等待時間的納秒數;
9.返回:
- 給定的最大等待時間減去等待花費時間的估計值。正數可以用于該方法的后續調用以完成等待所需時間。該值小于或等于0,表明沒有剩余的等待時間了,即無需再等待了。
10.拋出異常
- InterruptedException-中斷異常,如果當前線程被中斷(condition實現類支持線程掛起時中斷)
【2.4】boolean await(long time, TimeUnit unit) throws InterruptedException
1.導致當前線程等待直到接收到信號,或被中斷,或經過給定的等待時間。該方法等價于 awaitNanos(...) 方法,
awaitNanos(unit.toNanos(time)) > 02.參數
- time, 等待的最長時間;
- unit,time參數的單位,如時、分、秒
3.返回:
- 若方法返回前可以檢測到等待時間已經過去,則返回false;否則返回true;
- 即等待已超時,返回false,否則返回true;
4.拋出異常:
- InterruptedException-中斷異常,如果當前線程被中斷(condition實現類支持線程掛起時中斷)
【2.5】boolean awaitUntil(Date deadline) throws InterruptedException
1.導致當前線程等待直到收到信號,或中斷,或經過了給定的截止日期。
2.與condition關聯的鎖會被自動釋放,且當前線程會被線程調度器禁用并休眠,直到以下5種情況之一發生:
- 情況1,其他線程調用signal() 信號方法,且當前線程被選為要喚醒的線程;
- 情況2,其他線程調用 signalAll()方法;
- 情況3,其他線程中斷了當前線程(condition實現類支持線程掛起時中斷);
- 情況4,經過指定的截止日期;
- 情況5,發生虛假喚醒;
3.在所有情況下,在該方法從當前線程返回之前,當前線程都必須重新獲取與condition關聯的鎖。當線程返回時,能夠保證它持有鎖。
4.若在該方法入口設置了當前線程的中斷狀態,或等待時被中斷(且condition實現類支持線程掛起時被中斷),則線程將拋出InterruptedException-中斷異常,且當前線程的中斷狀態被清空。
對于第一種情況,在釋放鎖之前是否進行中斷測試沒有規定。
5.返回值 表明是否經過了截止期限,可以如下使用:
boolean aMethod(Date deadline) {boolean stillWaiting = true;lock.lock();try {while (!conditionBeingWaitedFor()) {if (!stillWaiting)return false;stillWaiting = theCondition.awaitUntil(deadline);// 等待,返回是否過了截止期限}// ...} finally {lock.unlock();}}6.實施注意事項
在本方法被調用時,假設當前線程持有了condition對象關聯的鎖。
這取決于condition實現類確定是否是這種情況,如果不是,如何響應。通常,會拋出異常(如IllegalMonitorStateException-非法監視器狀態異常),且condition實現類會記錄該事實。
7.在響應信號過程中,condition實現類傾向于響應中斷而不是方法正常返回或者超過給定截止時間。在任何情況下,condition實現類必須保證信號被重定向到其他等待線程(即,sinal發給其他線程以喚醒),如果有的話 。
8.參數
- deadline, 等待的絕對時間;
9.返回
- 如果經過了等待時間返回false, 否則true;
10.拋出異常:
- InterruptedException-中斷異常,如果當前線程被中斷(condition實現類支持線程掛起時中斷)
【2.6】void signal()
1.喚醒一個等待線程;
2.如果有多個線程在等待condition-條件,則其中一個線程將被選中進行喚醒。那個選中的線程在從await()方法返回之前,必須重新獲取鎖;
3.實施注意事項
該方法被調用時, condition實現類可能要求(通常要求)當前線程需要持有與condition對象關聯的鎖;condition實現類必須記錄這個先決條件以及在未持有鎖的情況下采取的任何動作;通常,會拋出異常,如IllegalMonitorStateException;
【2.7】void signalAll()
1.喚醒所有等待線程;
2.如果有線程在等待該條件,則所有等待線程都會被喚醒; 每個線程在從 await() 方法返回之前必須重新獲取鎖;
3.condition實現類注意事項
該方法被調用時, condition實現類可能要求(通常要求)當前線程需要持有與condition對象關聯的鎖;condition實現類必須記錄這個先決條件以及在未持有鎖的情況下采取的任何動作;通常,會拋出異常,如IllegalMonitorStateException;
【3】方法總結
【3.2】等待方法
| void await() throws InterruptedException | 該方法導致當前線程等待,直到收到信號或被中斷。 出現以下4種情況之一,線程恢復可運行狀態: 情況1,其他調用condition.signal(),且該線程被選中作為要喚醒的線程; 情況2,其他線程調用 condition.signalAll(), 喚醒所有等待線程; 情況3,發生中斷; 情況4,發送虛假喚醒; |
| void awaitUninterruptibly(); | 該方法導致當前線程等待,直到收到信號; 出現以下3種情況之一,線程恢復可運行狀態: 情況1,其他調用condition.signal(),且該線程被選中作為要喚醒的線程; 情況2,其他線程調用 condition.signalAll(), 喚醒所有等待線程; 情況3,發送虛假喚醒; |
| long awaitNanos(long nanosTimeout) throws InterruptedException; | 該方法導致當前線程等待,直到收到信號或被中斷或經過給定等待時間。 出現以5種情況之一,線程恢復可運行狀態: 情況1,其他調用condition.signal(),且該線程被選中作為要喚醒的線程; 情況2,其他線程調用 condition.signalAll(), 喚醒所有等待線程; 情況3,發生中斷; 情況4,經過給定的等待時間; 情況5,發送虛假喚醒; |
| boolean await(long time, TimeUnit unit) throws InterruptedException; | 導致當前線程等待直到接收到信號,或被中斷,或經過給定的等待時間。該方法等價于 awaitNanos(...) 方法, |
| boolean awaitUntil(Date deadline) throws InterruptedException; | 導致當前線程等待直到收到信號,或中斷,或經過了給定的截止日期。 出現以5種情況之一,線程恢復可運行狀態: 情況1,其他調用condition.signal(),且該線程被選中作為要喚醒的線程; 情況2,其他線程調用 condition.signalAll(), 喚醒所有等待線程; 情況3,發生中斷; 情況4,經過指定的截止日期; 情況5,發送虛假喚醒; |
【3.2】喚醒方法
| void signal() | 喚醒一個等待線程; 如果有多個線程在等待condition-條件,則其中一個線程將被選中進行喚醒。那個選中的線程在從await()方法返回之前,必須重新獲取鎖; |
| void signalAll() | 喚醒所有等待線程; 如果有線程在等待該條件,則所有等待線程都會被喚醒; 每個線程在從 await() 方法返回之前必須重新獲取鎖; |
總結
以上是生活随笔為你收集整理的java.util.concurrent.locks.Condition文档说明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java.util.concurrent
- 下一篇: 10人以下小团队管理手册-学习笔记