JavaTM 2 Platform
Standard Ed. 6

java.util.concurrent.locks
介面 Condition

所有已知實作類別:
AbstractQueuedLongSynchronizer.ConditionObject, AbstractQueuedSynchronizer.ConditionObject

public interface Condition

ConditionObject 監視器方法(waitnotifynotifyAll)分解成截然不同的物件,以便通過將這些物件與任意 Lock 實作組合使用,為每個物件提供多個等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監視器方法的使用。

條件(也稱為條件佇列條件變數)為執行緒提供了一個含義,以便在某個狀態條件現在可能為 true 的另一個執行緒通知它之前,一直掛起該執行緒(即讓其“等待”)。因為存取此共享狀態資訊發生在不同的執行緒中,所以它必須受保護,因此要將某種形式的鎖與該條件相關聯。等待提供一個條件的主要屬性是:以原子方式 釋放相關的鎖,並掛起當前執行緒,就像 Object.wait 做的那樣。

Condition 實例實質上被綁定到一個鎖上。要為特定 Lock 實例獲得 Condition 實例,請使用其 newCondition() 方法。

作為一個範例,假定有一個綁定的緩衝區,它支持 puttake 方法。如果試圖在空的緩衝區上執行 take 操作,則在某一個項變得可用之前,執行緒將一直阻塞;如果試圖在滿的緩衝區上執行 put 操作,則在有空間變得可用之前,執行緒將一直阻塞。我們喜歡在單獨的等待 set 中保存 put 執行緒和 take 執行緒,這樣就可以在緩衝區中的項或空間變得可用時利用最佳規劃,一次只通知一個執行緒。可以使用兩個 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();
     }
   } 
 }
 
ArrayBlockingQueue 類別提供了這項功能,因此沒有理由去實作這個範例類別。)

Condition 實作可以提供不同於 Object 監視器方法的行為和語義,比如受保證的通知排序,或者在執行通知時不需要保持一個鎖。如果某個實作提供了這樣特殊的語義,則該實作必須記錄這些語義。

注意,Condition 實例只是一些普通的物件,它們自身可以用作 synchronized 語句中的目標,並且可以調用自己的 waitnotification 監視器方法。獲取 Condition 實例的監視器鎖或者使用其監視器方法,與獲取和該 Condition 相關的 Lock 或使用其 waitingsignalling 方法沒有什麼特定的關係。為了避免混淆,建議除了在其自身的實作中之外,切勿以這種方式使用 Condition 實例。

除非另行說明,否則為任何參數傳遞 null 值將導致拋出 NullPointerException

實作注意事項

在等待 Condition 時,允許發生“虛假喚醒”,這通常作為對基礎平臺語義的讓步。對於大多數應用程序,這帶來的實際影響很小,因為 Condition 應該總是在一個循環中被等待,並測試正被等待的狀態宣告。某個實作可以隨意移除可能的虛假喚醒,但建議應用程序開發人員總是假定這些虛假喚醒可能發生,因此總是在一個循環中等待。

三種形式的條件等待(可中斷、不可中斷和逾時)在一些平臺上的實作以及它們的性能特徵可能會有所不同。尤其是它可能很難提供這些特性和維護特定語義,比如排序保證。更進一步地說,中斷執行緒實際掛起的能力在所有平臺上並不是總是可行的。

因此,並不要求某個實作為所有三種形式的等待定義完全相同的保證或語義,也不要求其支持中斷執行緒的實際掛起。

要求實作清楚地記錄每個等待方法提供的語義和保證,在某個實作不支持中斷執行緒的掛起時,它必須遵從此介面中定義的中斷語義。

由於中斷通常意味著取消,而又通常很少進行中斷檢查,因此實作可以先於普通方法的返回來對中斷進行回應。即使出現在另一個操作後的中斷可能會釋放執行緒鎖時也是如此。實作應記錄此行為。

從以下版本開始:
1.5

方法摘要
 void await()
          造成當前執行緒在接到信號或被中斷之前一直處於等待狀態。
 boolean await(long time, TimeUnit unit)
          造成當前執行緒在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。
 long awaitNanos(long nanosTimeout)
          造成當前執行緒在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。
 void awaitUninterruptibly()
          造成當前執行緒在接到信號之前一直處於等待狀態。
 boolean awaitUntil(Date deadline)
          造成當前執行緒在接到信號、被中斷或到達指定最後期限之前一直處於等待狀態。
 void signal()
          喚醒一個等待執行緒。
 void signalAll()
          喚醒所有等待執行緒。
 

方法詳細資訊

await

void await()
           throws InterruptedException
造成當前執行緒在接到信號或被中斷之前一直處於等待狀態。

與此 Condition 相關的鎖以原子方式釋放,並且出於執行緒排程的目的,將禁用當前執行緒,且在發生以下四種情況之一 以前,當前執行緒將一直處於休眠狀態:

在所有情況下,在此方法可以返回當前執行緒之前,都必須重新獲取與此條件有關的鎖。在執行緒返回時,可以保證 它保持此鎖。

如果當前執行緒:

則拋出 InterruptedException,並清除當前執行緒的中斷狀態。在第一種情況下,沒有指定是否在釋放鎖之前發生中斷測試。

實作注意事項

假定調用此方法時,當前執行緒保持了與此 Condition 有關聯的鎖。這取決於確定是否為這種情況以及不是時,如何對此作出回應的實作。通常,將拋出一個異常(比如 IllegalMonitorStateException)並且該實作必須對此進行記錄。

與回應某個信號而返回的普通方法相比,實作可能更喜歡回應某個中斷。在這種情況下,實作必須確保信號被重定向到另一個等待執行緒(如果有的話)。

拋出:
InterruptedException - 如果當前執行緒被中斷(並且支持中斷執行緒掛起)

awaitUninterruptibly

void awaitUninterruptibly()
造成當前執行緒在接到信號之前一直處於等待狀態。

與此條件相關的鎖以原子方式釋放,並且出於執行緒排程的目的,將禁用當前執行緒,且在發生以下三種情況之一 以前,當前執行緒將一直處於休眠狀態:

在所有情況下,在此方法可以返回當前執行緒之前,都必須重新獲取與此條件有關的鎖。在執行緒返回時,可以保證 它保持此鎖。

如果在進入此方法時設置了當前執行緒的中斷狀態,或者在等待時,執行緒被中斷,那麼在接到信號之前,它將繼續等待。當最終從此方法返回時,仍然將設置其中斷狀態。

實作注意事項

假定調用此方法時,當前執行緒保持了與此 Condition 有關聯的鎖。這取決於確定是否為這種情況以及不是時,如何對此作出回應的實作。通常,將拋出一個異常(比如 IllegalMonitorStateException)並且該實作必須對此進行記錄。


awaitNanos

long awaitNanos(long nanosTimeout)
                throws InterruptedException
造成當前執行緒在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。

與此條件相關的鎖以原子方式釋放,並且出於執行緒排程的目的,將禁用當前執行緒,且在發生以下五種情況之一 以前,當前執行緒將一直處於休眠狀態:

在所有情況下,在此方法可以返回當前執行緒之前,都必須重新獲取與此條件有關的鎖。在執行緒返回時,可以保證 它保持此鎖。

如果當前執行緒:

則拋出 InterruptedException,並且清除當前執行緒的已中斷狀態。在第一種情況下,沒有指定是否在釋放鎖之前發生中斷測試。

在返回時,該方法返回了所剩毫微秒數的一個估計值,以等待所提供的 nanosTimeout 值的時間,如果逾時,則返回一個小於等於 0 的值。可以用此值來確定在等待返回但某一等待條件仍不具備的情況下,是否要再次等待,以及再次等待的時間。此方法的典型用法採用以下形式:

 synchronized boolean aMethod(long timeout, TimeUnit unit) {
   long nanosTimeout = unit.toNanos(timeout);
   while (!conditionBeingWaitedFor) {
     if (nanosTimeout > 0)
         nanosTimeout = theCondition.awaitNanos(nanosTimeout);
      else
        return false;
   }
   // ... 
 }
 

設計注意事項:此方法需要一個 nanosecond 參數,以避免在報告剩餘時間時出現截斷錯誤。在發生重新等待時,這種精度損失使得開發人員難以確保總的等待時間不少於指定等待時間。

實作注意事項

假定調用此方法時,當前執行緒保持了與此 Condition 有關聯的鎖。這取決於確定是否為這種情況以及不是時,如何對此作出回應的實作。通常會拋出一個異常(比如 IllegalMonitorStateException)並且該實作必須對此進行記錄。

與回應某個信號而返回的普通方法相比,或者與指示所使用的指定等待時間相比,實作可能更喜歡回應某個中斷。在任意一種情況下,實作必須確保信號被重定向到另一個等待執行緒(如果有的話)。

參數:
nanosTimeout - 等待的最長時間,以毫微秒為單位
返回:
nanosTimeout 值減去花費在等待此方法的返回結果的時間的估算。正值可以用作對此方法進行後續調用的參數,來完成等待所需時間結束。小於等於零的值表示沒有剩餘時間。
拋出:
InterruptedException - 如果當前執行緒被中斷(並且支持中斷執行緒掛起)

await

boolean await(long time,
              TimeUnit unit)
              throws InterruptedException
造成當前執行緒在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。此方法在行為上等效於:
   awaitNanos(unit.toNanos(time)) > 0
 

參數:
time - 最長等待時間
unit - time 參數的時間單位
返回:
如果在從此方法返回前檢測到等待時間逾時,則返回 false,否則返回 true
拋出:
InterruptedException - 如果當前執行緒被中斷(並且支持中斷執行緒掛起)

awaitUntil

boolean awaitUntil(Date deadline)
                   throws InterruptedException
造成當前執行緒在接到信號、被中斷或到達指定最後期限之前一直處於等待狀態。

與此條件相關的鎖以原子方式釋放,並且出於執行緒排程的目的,將禁用當前執行緒,且在發生以下五種情況之一 以前,當前執行緒將一直處於休眠狀態:

在所有情況下,在此方法可以返回當前執行緒之前,都必須重新獲取與此條件有關的鎖。在執行緒返回時,可以保證 它保持此鎖。

如果當前執行緒:

則拋出 InterruptedException,並且清除當前執行緒的已中斷狀態。在第一種情況下,沒有指定是否在釋放鎖之前發生中斷測試。

返回值指示是否到達最後期限,使用方式如下:

 synchronized boolean aMethod(Date deadline) {
   boolean stillWaiting = true;
   while (!conditionBeingWaitedFor) {
     if (stillWaiting)
         stillWaiting = theCondition.awaitUntil(deadline);
      else
        return false;
   }
   // ... 
 }
 

實作注意事項

假定調用此方法時,當前執行緒保持了與此 Condition 有關聯的鎖。這取決於確定是否為這種情況以及不是時,如何對此作出回應的實作。通常,將拋出一個異常(比如 IllegalMonitorStateException)並且該實作必須對此進行記錄。

與回應某個信號而返回的普通方法相比,或者與指示是否到達指定最終期限相比,實作可能更喜歡回應某個中斷。在任意一種情況下,實作必須確保信號被重定向到另一個等待執行緒(如果有的話)。

參數:
deadline - 一直處於等待狀態的絕對時間
返回:
如果在返回時已經到達最後期限,則返回 false,否則返回 true
拋出:
InterruptedException - 如果當前執行緒被中斷(並且支持中斷執行緒掛起)

signal

void signal()
喚醒一個等待執行緒。

如果所有的執行緒都在等待此條件,則選擇其中的一個喚醒。在從 await 返回之前,該執行緒必須重新獲取鎖。


signalAll

void signalAll()
喚醒所有等待執行緒。

如果所有的執行緒都在等待此條件,則喚醒所有執行緒。在從 await 返回之前,每個執行緒都必須重新獲取鎖。


JavaTM 2 Platform
Standard Ed. 6

提交錯誤或意見

版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only