-
- 既知のすべての実装クラス:
AbstractQueuedLongSynchronizer.ConditionObject
,AbstractQueuedSynchronizer.ConditionObject
public interface Condition
Condition
は、Object
監視メソッド(wait
、notify
、およびnotifyAll
)を別個のオブジェクトに分解し、それらに任意のLock
実装の使用を組み合わせて、オブジェクトごとに複数の待機セットを保持する効果を付与します。 ここで、Lock
はsynchronized
メソッドおよび文の使用を置き換え、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
-
-
メソッドのサマリー
修飾子と型 メソッド 説明 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つのいずれかが起きるまで待機します。- ほかのスレッドがこの
Condition
に対してsignal()
メソッドを呼び出し、現在のスレッドが起動スレッドとして選択される。 - ほかのスレッドがこの
Condition
に対してsignalAll()
メソッドを呼び出した。 - ほかのスレッドが現在のスレッドに割り込みを行い、スレッド中断の割込みがサポートされる。
- 「見せかけの起動」が発生する。
いずれの場合でも、このメソッドが現在のスレッドを返す前に、この状態に関連付けられたロックを再取得する必要があります。 スレッドの復帰時に、このロックを保持することが保証されます。
現在のスレッドで、
- このメソッドへのエントリ上で設定された割込みステータスが保持されるか、
- スレッドの待機および中断がサポートされている状況で、割り込みが発生する場合、
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。 初回時には、ロックが解放される前に割り込みのテストが実行されるかどうかは指定されません。実装上の考慮事項
このメソッドの呼出し時に、現在のスレッドは、この
Condition
に関連付けられているロックを保持するものとみなされます。 これが応答方法を決定する要因になるかどうかは、実装によって異なります。 通常、(IllegalMonitorStateException
などの)例外がスローされ、実装はそのことをドキュメント化する必要があります。実装は、信号に応答して実行される通常のメソッド復帰に対する割り込みに肯定的に応答できます。 この場合、実装は、別の待機スレッドが存在する場合に、信号がそのスレッドに確実にリダイレクトされるようにする必要があります。
- 例外:
InterruptedException
- 現在のスレッドで割込みが発生する(およびスレッド中断の割込みがサポートされる)場合
- ほかのスレッドがこの
-
awaitUninterruptibly
void awaitUninterruptibly()
現在のスレッドを、信号が送られるまで待機させます。この状態に関連付けられているロックは原子的に解放されます。また、現在のスレッドはスレッドのスケジューリングとしては無効になり、次の3つのいずれかが起きるまで待機します。
- ほかのスレッドがこの
Condition
に対してsignal()
メソッドを呼び出し、現在のスレッドが起動スレッドとして選択される。 - ほかのスレッドがこの
Condition
に対してsignalAll()
メソッドを呼び出した。 - 「見せかけの起動」が発生する。
いずれの場合でも、このメソッドが現在のスレッドを返す前に、この状態に関連付けられたロックを再取得する必要があります。 スレッドの復帰時に、このロックを保持することが保証されます。
現在のスレッドがこのメソッドに入るときにその割込み状態が設定されるか、または待機中に割り込みが発生する場合は、信号が送信されるまで待機が継続されます。 このメソッドからの最終復帰時にも、割込み状態は引き続き設定されます。
実装上の考慮事項
このメソッドの呼出し時に、現在のスレッドは、この
Condition
に関連付けられているロックを保持するものとみなされます。 これが応答方法を決定する要因になるかどうかは、実装によって異なります。 通常、(IllegalMonitorStateException
などの)例外がスローされ、実装はそのことをドキュメント化する必要があります。 - ほかのスレッドがこの
-
awaitNanos
long awaitNanos(long nanosTimeout) throws InterruptedException
信号が送信される、割込みが発生する、または指定された待機時間が経過するまで、現在のスレッドを待機させます。この状態に関連付けられているロックは原子的に解放されます。また、現在のスレッドはスレッドのスケジューリングとしては無効になり、次の5つのいずれかが起きるまで待機します。
- ほかのスレッドがこの
Condition
に対してsignal()
メソッドを呼び出し、現在のスレッドが起動スレッドとして選択される。 - ほかのスレッドがこの
Condition
に対してsignalAll()
メソッドを呼び出した。 - ほかのスレッドが現在のスレッドに割り込みを行い、スレッド中断の割込みがサポートされる。
- 指定された待機時間が経過する。または
- 「見せかけの起動」が発生する。
いずれの場合でも、このメソッドが現在のスレッドを返す前に、この状態に関連付けられたロックを再取得する必要があります。 スレッドの復帰時に、このロックを保持することが保証されます。
現在のスレッドで、
- このメソッドへのエントリ上で設定された割込みステータスが保持されるか、
- スレッドの待機および中断がサポートされている状況で、割り込みが発生する場合、
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。 初回時には、ロックが解放される前に割り込みのテストが実行されるかどうかは指定されません。このメソッドは、復帰時に、指定された
nanosTimeout
値に対する待機する残りの推定ナノ秒数を返します。または、タイム・アウトした場合はゼロ以下の値を返します。 待機が復帰しても待機状態が依然として保持されない場合に、この値を使用して、再度待機するかどうか、およびその期間を決定できます。 通常、このメソッドは次の形式になります。boolean aMethod(long timeout, TimeUnit unit) throws InterruptedException { long nanosRemaining = unit.toNanos(timeout); lock.lock(); try { while (!conditionBeingWaitedFor()) { if (nanosRemaining <= 0L) return false; nanosRemaining = theCondition.awaitNanos(nanosRemaining); } // ... return true; } finally { lock.unlock(); } }
設計上の注意: このメソッドは、残り時間をレポートする際に切詰めエラーの発生を避けるためにナノ秒の引数を指定する必要があります。 この精度が低下すると、待機時間の合計が、指定された再待機の発生時よりもシステム的に短くないことをプログラマが保証することが難しくなります。
実装上の考慮事項
このメソッドの呼出し時に、現在のスレッドは、この
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つのいずれかが起きるまで待機します。
- ほかのスレッドがこの
Condition
に対してsignal()
メソッドを呼び出し、現在のスレッドが起動スレッドとして選択される。 - ほかのスレッドがこの
Condition
に対してsignalAll()
メソッドを呼び出した。 - ほかのスレッドが現在のスレッドに割り込みを行い、スレッド中断の割込みがサポートされる。
- 指定された期限が経過する。または
- 「見せかけの起動」が発生する。
いずれの場合でも、このメソッドが現在のスレッドを返す前に、この状態に関連付けられたロックを再取得する必要があります。 スレッドの復帰時に、このロックを保持することが保証されます。
現在のスレッドで、
- このメソッドへのエントリ上で設定された割込みステータスが保持されるか、
- スレッドの待機および中断がサポートされている状況で、割り込みが発生する場合、
InterruptedException
がスローされ、現在のスレッドの割込みステータスがクリアされます。 初回時には、ロックが解放される前に割り込みのテストが実行されるかどうかは指定されません。戻り値は、期限が経過したかどうかを示します。この値は次のように使用できます。
boolean aMethod(Date deadline) throws InterruptedException { boolean stillWaiting = true; lock.lock(); try { while (!conditionBeingWaitedFor()) { if (!stillWaiting) return false; stillWaiting = theCondition.awaitUntil(deadline); } // ... return true; } finally { lock.unlock(); } }
実装上の考慮事項
このメソッドの呼出し時に、現在のスレッドは、この
Condition
に関連付けられているロックを保持するものとみなされます。 これが応答方法を決定する要因になるかどうかは、実装によって異なります。 通常、(IllegalMonitorStateException
などの)例外がスローされ、実装はそのことをドキュメント化する必要があります。実装は、信号に応答して実行される通常のメソッド復帰に対する割り込み、または指定された期限の経過指示に対する割り込みに肯定的に応答できます。 どちらの場合も、実装は、別の待機スレッドが存在する場合に、信号がそのスレッドに確実にリダイレクトされるようにする必要があります。
- パラメータ:
deadline
- 待機する絶対時間- 戻り値:
false
- 復帰時に期限が経過している場合。そうでない場合はtrue
- 例外:
InterruptedException
- 現在のスレッドで割込みが発生する(およびスレッド中断の割込みがサポートされる)場合
- ほかのスレッドがこの
-
signal
void signal()
待機中のスレッドを1つ起動します。この状態で待機中のスレッドが存在する場合、1つのスレッドが起動用に選択されます。 そのスレッドは、そのあと、
await
から復帰する前にロックを再取得する必要があります。実装上の考慮事項
実装では、このメソッドが呼び出されたとき、現在のスレッドがこの
Condition
に関連付けられたロックを保持することが必要になることがあります(通常は必要です)。 実装では、この事前条件と、ロックが保持されない場合に実行されるアクションをドキュメント化する必要があります。 通常、IllegalMonitorStateException
などの例外がスローされます。
-
signalAll
void signalAll()
待機中のすべてのスレッドを起動します。この状態で待機中のスレッドが存在する場合、すべてのスレッドが起動されます。 各スレッドは、
await
から復帰する前にロックを再取得する必要があります。実装上の考慮事項
実装では、このメソッドが呼び出されたとき、現在のスレッドがこの
Condition
に関連付けられたロックを保持することが必要になることがあります(通常は必要です)。 実装では、この事前条件と、ロックが保持されない場合に実行されるアクションをドキュメント化する必要があります。 通常、IllegalMonitorStateException
などの例外がスローされます。
-
-