モジュール java.base

インタフェースCondition

既知のすべての実装クラス:
AbstractQueuedLongSynchronizer.ConditionObject, AbstractQueuedSynchronizer.ConditionObject

public interface Condition
Conditionは、Object監視メソッド(waitnotify、およびnotifyAll)を別個のオブジェクトに分解し、それらに任意のLock実装の使用を組み合わせて、オブジェクトごとに複数の待機セットを保持する効果を付与します。 ここで、Locksynchronizedメソッドおよび文の使用を置き換え、ConditionはObject監視メソッドの使用を置き換えます。

状態(状態キューまたは状態変数とも呼ばれる)は、何らかの状態がtrueになっている可能性があることが別のスレッドによって通知されるまで、スレッドが実行を中断(「待機」)するための手段を提供します。 この共有状態情報へのアクセスは別のスレッド内で行われるため、このアクセスを保護する必要があります。このため、なんらかの形式のロックがこの状態と関連付けられています。 状態の待機によって提供される主な特性は、Object.waitと同様に、関連付けられたロックを原子的に解放し、現在のスレッドを中断することです。

Conditionインスタンスは、本質的にロックにバインドされています。 特定のLockインスタンスのためのConditionインスタンスを取得するには、そのnewCondition()メソッドを使用します。

例として、putメソッドとtakeメソッドをサポートするバウンド・バッファがあるとします。 空のバッファに対してtakeが試行された場合は、項目が使用可能になるまでスレッドがブロックされます。いっぱいのバッファに対してputが試行された場合は、容量が使用可能になるまでスレッドがブロックされます。 バッファ内で項目または容量が使用可能になったときに1回につき1つのスレッドにのみ通知する最適化を使用できるように、putスレッドとtakeスレッドを個別の待機セット内で待機した状態に維持することにします。 これは、2つのConditionインスタンスを使用して実現できます。

 class BoundedBuffer<E> {
   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(E 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 E take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       E x = (E) items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
 }
 
(ArrayBlockingQueueクラスにはこの機能があるため、この使用例のクラスを実装する必要はありません。)

Condition実装は、通知の順序付けが保証されることや、通知の実行時にロックを保持する必要がないことなど、Object監視メソッドとは異なる動作やセマンティックスを提供できます。 実装がこうした特殊セマンティックスを提供する場合、実装はこれらのセマンティックスをドキュメント化する必要があります。

Conditionインスタンスは通常のオブジェクトであり、それ自体をsynchronized文のターゲットとして使用でき、独自のモニターwaitおよびnotifyメソッドを起動できます。 Conditionインスタンスの監視ロックの取得、またはその監視メソッドの使用は、そのConditionに関連付けられたLockの取得または、その待機および信号送信メソッドの使用とは特に関係がありません。 混乱を避けるために、独自の実装内で行う場合を除き、Conditionインスタンスをこの方法では決して使用しないようにすることをお薦めします。

特に記載がないかぎり、パラメータにnull値を渡すとNullPointerExceptionがスローされます。

実装上の考慮事項

Conditionの待機中に、基本となるプラットフォーム・セマンティクスへの譲歩として、通常、「見せかけの起動」が許可されます。 Conditionは、ループ上で常に待機して、待機対象の状態予測をテストする必要があるため、これはたいていのアプリケーション・プログラムでは実質的な効果はほとんどありません。 実装は見せかけの起動の可能性を自由に削除できますが、アプリケーション・プログラマはそれが発生し、ループ上で常に待機するものと想定することをお薦めします。

状態待機の3つの形式(割込み可、割込み不可、および時間指定)では、プラットフォームでの実装の容易性およびパフォーマンス特性が異なります。 特に、これらの機能を提供しつつ、順序付け保証などの特定のセマンティックスを維持することが困難な場合があります。 さらに、実際のスレッド中断に割り込む機能をすべてのプラットフォームで実装することは、常に実行可能であるとは限りません。

したがって、実装が、3つの待機形式すべてで同一の保証やセマンティックスを定義することは要求されていません。また、実際のスレッド中断に対する割込みをサポートする必要もありません。

実装は、待機中の各メソッドで提供されるセマンティックスや保証、および実装がスレッド中断の割込みをサポートし、このインタフェースで定義された割込みセマンティックスに従う必要がある場合を明確にドキュメント化する必要があります。

通常、割込みは取消しを意味し、割り込みのチェックは頻繁に行われるものではないため、実装は通常のメソッド復帰に対する割り込みに肯定的に応答できます。 これは、スレッドをブロック解除した可能性のある別のアクションのあとに割込みが発生したことが示される場合でも当てはまります。 実装は、この動作をドキュメント化する必要があります。

導入されたバージョン:
1.5