JavaTM Platform
Standard Ed. 6

java.util.concurrent.locks
インタフェース 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 が試みられると、空間が利用可能になるまでスレッドがブロックします。バッファー内で項目または空間が利用可能になった時点で単一スレッド通知だけの最適化を使用できるように、put スレッドと take スレッドを別個の待機セット内で待機させることにします。これは、2 つの 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 文のターゲットに使用できること、および独自の監視の待機および通知メソッドを呼び出せることに留意してください。Condition インスタンスの監視ロックの取得、またはその監視メソッドの使用は、Condition に関連付けられた Lock の取得または待機および信号送信メソッドの使用とは特に関係がありません。混乱を避けるため、独自実装の内部を除き、Condition インスタンスをこのような方法では決して使用しないようにしてください。

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

実装上の考慮事項

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

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

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

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

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

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

メソッドの概要
 void await()
          信号が送信されるか、割り込みが発生するまで、現在のスレッドを待機させます。
 boolean await(long time, TimeUnit unit)
          信号が送信される、割り込みが発生する、または指定された待機時間が経過するまで、現在のスレッドを待機させます。
 long awaitNanos(long nanosTimeout)
          信号が送信される、割り込みが発生する、または指定された待機時間が経過するまで、現在のスレッドを待機させます。
 void awaitUninterruptibly()
          現在のスレッドを、信号が送られるまで待機させます。
 boolean awaitUntil(Date deadline)
          信号が送信される、割り込みが発生する、または指定された期限が経過するまで、現在のスレッドを待機させます。
 void signal()
          待機中のスレッドを 1 つ起動します。
 void signalAll()
          待機中のすべてのスレッドを起動します。
 

メソッドの詳細

await

void await()
           throws InterruptedException
信号が送信されるか、割り込みが発生するまで、現在のスレッドを待機させます。

この Condition に関連付けられているロックは原子的に解放されます。また、現在のスレッドはスレッドのスケジューリングとしては無効になり、次の 4 つのいずれかが起きるまで待機します。

いずれの場合でも、このメソッドが現在のスレッドを返す前に、この状態に関連付けられたロックを再取得する必要があります。スレッドの復帰時に、このロックを保持することが保証されます。

現在のスレッドで、

InterruptedException がスローされ、現在のスレッドの割り込みステータスがクリアされます。初回時には、ロックが解放される前に割り込みのテストが実行されるかどうかは指定されません。

実装上の考慮事項

このメソッドの呼び出し時に、現在のスレッドは、この Condition に関連付けられているロックを保持するものとみなされます。これが応答方法を決定する要因になるかどうかは、実装によって異なります。通常、(IllegalMonitorStateException などの) 例外がスローされ、実装はそのことをドキュメント化する必要があります。

実装は、信号に応答して実行される通常のメソッド復帰に対する割り込みに肯定的に応答できます。この場合、実装は、別の待機スレッドが存在する場合に、信号がそのスレッドに確実にリダイレクトされるようにする必要があります。

例外:
InterruptedException - 現在のスレッドで割り込みが発生する (およびスレッド中断の割り込みがサポートされる) 場合

awaitUninterruptibly

void awaitUninterruptibly()
現在のスレッドを、信号が送られるまで待機させます。

この状態に関連付けられているロックは原子的に解放されます。また、現在のスレッドはスレッドのスケジューリングとしては無効になり、次の 3 つのいずれかが起きるまで待機します。

いずれの場合でも、このメソッドが現在のスレッドを返す前に、この状態に関連付けられたロックを再取得する必要があります。スレッドの復帰時に、このロックを保持することが保証されます。

現在のスレッドがこのメソッドに入るときに割り込み状態が設定されるか、待機中に割り込みが発生する場合、信号が送信されるまで待機が継続されます。このメソッドからの最終復帰時にも、「割り込み状態」は引き続き設定されます。

実装上の考慮事項

このメソッドの呼び出し時に、現在のスレッドは、この Condition に関連付けられているロックを保持するものとみなされます。これが応答方法を決定する要因になるかどうかは、実装によって異なります。通常、(IllegalMonitorStateException などの) 例外がスローされ、実装はそのことをドキュメント化する必要があります。


awaitNanos

long awaitNanos(long nanosTimeout)
                throws InterruptedException
信号が送信される、割り込みが発生する、または指定された待機時間が経過するまで、現在のスレッドを待機させます。

この状態に関連付けられているロックは原子的に解放されます。また、現在のスレッドはスレッドのスケジューリングとしては無効になり、次の 5 つのいずれかが起きるまで待機します。

いずれの場合でも、このメソッドが現在のスレッドを返す前に、この状態に関連付けられたロックを再取得する必要があります。スレッドの復帰時に、このロックを保持することが保証されます。

現在のスレッドで、

InterruptedException がスローされ、現在のスレッドの割り込みステータスがクリアされます。初回時には、ロックが解放される前に割り込みのテストが実行されるかどうかは指定されません。

このメソッドは、復帰時に、指定された待機時間を示す nanosTimeout 値に対する残りの推定ナノ秒数を返します。タイムアウト時間が経過している場合は、ゼロまたはゼロ未満の値を返します。待機が復帰しても待機状態が依然として保持されない場合に、この値を使用して、再度待機するかどうか、およびその期間を決定できます。通常、このメソッドは次の形式になります。

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

設計上の注意:このメソッドは、残り時間をレポートする際に切り詰めエラーの発生を避けるためにナノ秒の引数を指定する必要があります。この精度が低下すると、待機時間の合計が、指定された再待機の発生時よりもシステム的に短くないことをプログラマが保証することが難しくなります。

実装上の考慮事項

このメソッドの呼び出し時に、現在のスレッドは、この 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
信号が送信される、割り込みが発生する、または指定された期限が経過するまで、現在のスレッドを待機させます。

この状態に関連付けられているロックは原子的に解放されます。また、現在のスレッドはスレッドのスケジューリングとしては無効になり、次の 5 つのいずれかが起きるまで待機します。

いずれの場合でも、このメソッドが現在のスレッドを返す前に、この状態に関連付けられたロックを再取得する必要があります。スレッドの復帰時に、このロックを保持することが保証されます。

現在のスレッドで、

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()
待機中のスレッドを 1 つ起動します。

この状態で待機中のスレッドが存在する場合、1 つのスレッドが起動用に選択されます。このスレッドは、await から復帰する前にロックを再取得する必要があります。


signalAll

void signalAll()
待機中のすべてのスレッドを起動します。

この状態で待機中のスレッドが存在する場合、すべてのスレッドが起動されます。各スレッドは、await から復帰する前にロックを再取得する必要があります。


JavaTM Platform
Standard Ed. 6

バグの報告と機能のリクエスト
さらに詳しい API リファレンスおよび開発者ドキュメントについては、Java SE 開発者用ドキュメントを参照してください。開発者向けの詳細な解説、概念の概要、用語の定義、バグの回避策、およびコード実例が含まれています。

Copyright 2006 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。