|
JavaTM 2 Platform Standard Ed. 5.0 |
|||||||||
前のクラス 次のクラス | フレームあり フレームなし | |||||||||
概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド |
java.lang.Object java.util.concurrent.Semaphore
public class Semaphore
カウントに使用されるセマフォ。概念的には、セマフォは許可セットを管理します。各 acquire()
は、必要に応じ、パーミットが利用可能になるまでブロックを実行し、利用可能になるとそれを取得します。各 release()
はパーミットを追加しますが、その際ブロック取得者を解放する可能性があります。ただし、実際のパーミットオブジェクトは使用されません。Semaphore は利用可能な数のカウントを維持し、それに応じて動作するだけです。
セマフォは、一部の (物理または論理) リソースにアクセス可能なスレッドの数を制限する場合にしばしば使用されます。たとえば、以下に示すクラスは、項目のプールへのアクセス制御にセマフォを使用します。
class Pool { private static final MAX_AVAILABLE = 100; private final Semaphore available = new Semaphore(MAX_AVAILABLE, true); public Object getItem() throws InterruptedException { available.acquire(); return getNextAvailableItem(); } public void putItem(Object x) { if (markAsUnused(x)) available.release(); } // Not a particularly efficient data structure; just for demo protected Object[] items = ... whatever kinds of items being managed protected boolean[] used = new boolean[MAX_AVAILABLE]; protected synchronized Object getNextAvailableItem() { for (int i = 0; i < MAX_AVAILABLE; ++i) { if (!used[i]) { used[i] = true; return items[i]; } } return null; // not reached } protected synchronized boolean markAsUnused(Object item) { for (int i = 0; i < MAX_AVAILABLE; ++i) { if (item == items[i]) { if (used[i]) { used[i] = false; return true; } else return false; } } return false; } }
項目を取得する前に、各スレッドはセマフォから項目が使用可能であることを保証するパーミットを取得する必要があります。項目処理が完了するとスレッドはプールに戻り、パーミットがセマフォに返され、別のスレッドが項目を取得できるようになります。acquire()
の呼び出し時に同期ロックは保持されません。同期ロックが保持されると、項目をプールに返すことができなくなるためです。セマフォは、プールへのアクセス制限に必要な同期を、プール自体の一貫性維持に必要な同期とは別個にカプセル化します。
セマフォは初期化されると、パーミットを最大 1 つ使用可能にするため、相互排他ロックとして機能することが可能です。これは、1 つのパーミットを使用可能にする状態とゼロのパーミットを使用可能にする状態の 2 つだけを保持するため、一般的には「バイナリセマフォ」として知られています。この方法で使用される場合、バイナリセマフォは (多くの Lock
実装とは異なり) 「ロック」を所有者以外のスレッドにより解放可能であるというプロパティを保持します (セマフォには所有権という概念がないため)。これは、デッドロックの復元など、一部の特殊なコンテキストでは有用です。
このクラスのコンストラクタは、オプションで fairness パラメータを受け入れます。これを false に設定すると、このクラスはスレッドがパーミットを取得する順番を保証しません。特に、「バージング」が許可されます。これは、acquire()
を呼び出すスレッドが待機していたスレッドに先立ってパーミットを割り当てられることを意味します。論理的には、新しい方のスレッドが待機中のスレッドのキューの先頭に配置されることになります。fairness が true に設定されると、セマフォは、いずれかの取得
メソッドを呼び出すスレッドが、これらのメソッドが処理される順番 (先入れ先出し; FIFO) でパーミットを取得するように選択されることを保証します。FIFO 順は、必然的に、これらのメソッド内の特定の内部実行ポイントに適用されます。このため、あるスレッドが別のスレッドより前に acquire を呼び出すが、他のスレッドよりも後に順序ポイントに達する場合があります。また、メソッドからの復帰時に同様のことが起こる可能性もあります。さらに、時間設定されていない tryAcquire
メソッドは均等設定を尊重しませんが、使用可能なパーミットは受け入れます。
通常、リソースへのアクセス制御に使用するセマフォは、均等性を保つように初期化して、リソースへのアクセスが困難になるスレッドが存在しないようにする必要があります。他の種類の同期制御でセマフォを使用する場合、非均等の順序付けによるスループットの利点が均等性の考慮よりもしばしば重要になります。
このクラスは、一度に複数のパーミットを取得
および解放
するための便利なメソッドも提供します。均等性を true に設定せずにこれらのメソッドを使用する場合、無制限に延期される危険が増すことに留意してください。
コンストラクタの概要 | |
---|---|
Semaphore(int permits)
指定された数のパーミットおよび非均等設定を使用して Semaphore を作成します。 |
|
Semaphore(int permits,
boolean fair)
指定数のパーミットおよび指定された均等設定を使用して Semaphore を作成します。 |
メソッドの概要 | |
---|---|
void |
acquire()
このセマフォからパーミットを取得し、利用可能になるまでブロックを実行します。 |
void |
acquire(int permits)
このセマフォから指定数のパーミットを取得し、すべてが利用可能になるまでブロックを実行します。 |
void |
acquireUninterruptibly()
このセマフォからパーミットを取得します。 |
void |
acquireUninterruptibly(int permits)
指定数のパーミットをこのセマフォから取得し、すべてが利用可能になるまでブロックします。 |
int |
availablePermits()
このセマフォで利用可能な現在のパーミット数を返します。 |
int |
drainPermits()
すぐに利用可能なパーミットをすべて取得して返す |
protected Collection<Thread> |
getQueuedThreads()
取得を待機しているスレッドを含むコレクションを返します。 |
int |
getQueueLength()
取得を待機中のスレッドの推定数を返します。 |
boolean |
hasQueuedThreads()
取得を待機中のスレッドが存在するかどうかを照会します。 |
boolean |
isFair()
このセマフォで均等性が true に設定されている場合は true を返します。 |
protected void |
reducePermits(int reduction)
利用可能なパーミットの数を、指定された数だけ減らします。 |
void |
release()
パーミットを解放してセマフォに返します。 |
void |
release(int permits)
指定数のパーミットを解放して、セマフォに返します。 |
String |
toString()
このセマフォおよびその状態を識別する文字列を返します。 |
boolean |
tryAcquire()
呼び出し時にパーミットが利用可能である場合にのみ、このセマフォからパーミットを取得します。 |
boolean |
tryAcquire(int permits)
呼び出し時に指定数のパーミットをすべて利用可能な場合にのみ、パーミットをこのセマフォから取得します。 |
boolean |
tryAcquire(int permits,
long timeout,
TimeUnit unit)
指定された待機時間内に指定数のパーミットがすべて利用可能になり、現在のスレッドで 割り込み が発生していない場合に、それらのパーミットをこのセマフォから取得します。 |
boolean |
tryAcquire(long timeout,
TimeUnit unit)
指定された待機時間内にパーミットが利用可能になり、現在のスレッドで 割り込み が発生していない場合に、このセマフォからパーミットを取得します。 |
クラス java.lang.Object から継承されたメソッド |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
コンストラクタの詳細 |
---|
public Semaphore(int permits)
permits
- 使用可能なパーミットの初期数。これは負の値にすることもできます。値が負の場合、どの取得が許可されるよりも前に解放を行う必要があります。public Semaphore(int permits, boolean fair)
permits
- 使用可能なパーミットの初期数。これは負の値にすることもできます。値が負の場合、どの取得が許可されるよりも前に解放を行う必要があります。fair
- 競合の発生時にこのセマフォが先入れ先出しのパーミット許可を保証する場合は true、そうでない場合は falseメソッドの詳細 |
---|
public void acquire() throws InterruptedException
割り込み
が発生します。
パーミットが利用可能な場合はそれを取得してただちに復帰し、利用可能なパーミットの数を 1 つ減らします。
パーミットを利用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 2 つのいずれかが起きるまで待機します。
現在のスレッドで、
割り込み
が発生した場合、
InterruptedException
がスローされ、現在のスレッドの割り込みステータスがクリアされます。
InterruptedException
- 現在のスレッドで割り込みが発生した場合Thread.interrupt()
public void acquireUninterruptibly()
パーミットが利用可能な場合はそれを取得してただちに復帰し、利用可能なパーミットの数を 1 つ減らします。
パーミットを利用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、他のスレッドがこのセマフォに対して release()
メソッドを呼び出し、次にパーミットを割り当てられるのが現在のスレッドになるまで待機します。
パーミットの待機中に現在のスレッドで割り込み
が発生した場合、待機は続行されますが、スレッドがパーミットを割り当てられる時は、パーミットで割り込みが発生しなかった場合に受け取る時とは異なる場合があります。スレッドがメソッドから復帰する際に、割り込み状態が設定されます。
public boolean tryAcquire()
パーミットが利用可能な場合はそれを取得し、値 true でただちに復帰して、利用可能なパーミットの数を 1 つ減らします。
パーミットを利用できない場合、このメソッドは値 false でただちに復帰します。
このセマフォが均等順序付けポリシーを使用するように設定されている場合でも、パーミットが利用可能であれば、他のスレッドが現在、待機中であるかどうかに関係なく、tryAcquire() の呼び出しによりただちにそれを取得します。この「バージング」動作は、均等性を損なうとしても、特定の状況で有用なものになります。均等設定を重視する場合、ほぼ等価な tryAcquire(0, TimeUnit.SECONDS)
を使用してください (これも割り込みを検出する)。
public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException
割り込み
が発生していない場合に、このセマフォからパーミットを取得します。
パーミットが利用可能な場合はそれを取得し、値 true でただちに復帰して、利用可能なパーミットの数を 1 つ減らします。
パーミットを利用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 3 つのいずれかが起きるまで待機します。
パーミットが取得されると、値 true が返されます。
現在のスレッドで、
割り込み
が発生した場合、
InterruptedException
がスローされ、現在のスレッドの割り込みステータスがクリアされます。
指定された待機時間が経過すると、値 false が返されます。時間がゼロまたはそれより小さい場合、メソッドは待機しません。
timeout
- パーミットの最長待機時間unit
- timeout 引数の時間単位
InterruptedException
- 現在のスレッドで割り込みが発生した場合Thread.interrupt()
public void release()
パーミットを解放し、利用可能なパーミットの数を 1 増やします。いずれかのスレッドがパーミットの取得を試みる場合、それが選択され、解放されたばかりのパーミットが与えられます。そのスレッドは、スレッドスケジューリングに関して再度有効にされます。
パーミットを解放するスレッドが、acquire()
を呼び出してパーミットを取得済みである必要はありません。セマフォの適正な使用法は、アプリケーションのプログラミング規約により確立されます。
public void acquire(int permits) throws InterruptedException
割り込み
が発生します。
指定数のパーミットが利用可能な場合にそれを取得し、ただちに復帰して、利用可能なパーミットの数を指定数だけ減らします。
利用可能なパーミットの数が不足している場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 2 つのいずれかが起きるまで待機します。
release
メソッドのいずれかを呼び出し、次にパーミットが割り当てられるのが現在のスレッドで、利用可能なパーミットの数がこの要求を満たす割り込み
を行う 現在のスレッドで、
割り込み
が発生した場合、
InterruptedException
がスローされ、現在のスレッドの割り込み状態がクリアされます。このスレッドに割り当てられるはずのパーミットは、release()
の呼び出しで利用可能になったかのように、パーミットの取得を試みる他のスレッドに割り当てられます。
permits
- 取得するパーミットの数
InterruptedException
- 現在のスレッドで割り込みが発生した場合
IllegalArgumentException
- パーミットがゼロ未満の場合Thread.interrupt()
public void acquireUninterruptibly(int permits)
指定数のパーミットが利用可能な場合にそれを取得し、ただちに復帰して、利用可能なパーミットの数を指定数だけ減らします。
十分な数のパーミットを利用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になります。その後、他のスレッドがこのセマフォに対して release
メソッドのいずれかを呼び出し、次回パーミットを割り当てられるのが現在のスレッドで、利用可能なパーミットの数がこの要求を満たすまで待機します。
パーミットの待機中に現在のスレッドで割り込み
が発生する場合、待機は継続され、キュー内の位置は影響を受けません。スレッドがこのメソッドから復帰する際、割り込み状態が設定されます。
permits
- 取得するパーミットの数
IllegalArgumentException
- パーミットがゼロ未満の場合public boolean tryAcquire(int permits)
指定数のパーミットが利用可能な場合にそれを取得し、ただちに true で復帰して、利用可能なパーミットの数を指定数だけ減らします。
利用可能なパーミットの数が不十分な場合、このメソッドは値 false でただちに復帰します。利用可能なパーミットの数は変化しません。
このセマフォが均等順序付けポリシーを使用するように設定されている場合でも、パーミットが利用可能であれば、他のスレッドが待機中であるかどうかに関係なく、tryAcquire の呼び出しによりただちにそれを取得します。この「バージング」動作は、均等性を損なうとしても、特定の状況で有用なものになります。均等設定を重視する場合、ほぼ等価な tryAcquire(permits, 0, TimeUnit.SECONDS)
を使用してください (これも割り込みを検出する)。
permits
- 取得するパーミットの数
IllegalArgumentException
- パーミットがゼロ未満の場合public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException
割り込み
が発生していない場合に、それらのパーミットをこのセマフォから取得します。
指定数のパーミットが利用可能な場合にそれを取得し、ただちに値 true で復帰して、利用可能なパーミットの数を指定数だけ減らします。
利用可能なパーミットの数が不足している場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 3 つのいずれかが起きるまで待機します。
release
メソッドのいずれかを呼び出し、次にパーミットが割り当てられるのが現在のスレッドで、利用可能なパーミットの数がこの要求を満たす割り込み
を行う パーミットが取得されると、値 true が返されます。
現在のスレッドで、
割り込み
が発生した場合、
InterruptedException
がスローされ、現在のスレッドの割り込み状態がクリアされます。このスレッドに割り当てられるはずのパーミットは、release()
の呼び出しで利用可能になったかのように、パーミットの取得を試みる他のスレッドに割り当てられます。
指定された待機時間が経過すると、値 false が返されます。時間がゼロ以下の場合、メソッドは待機しません。このスレッドに割り当てられるはずのパーミットはすべて、release()
の呼び出しにより利用可能にされたかのように、パーミットの取得を試みる他のスレッドに代わりに割り当てられます。
permits
- 取得するパーミットの数timeout
- パーミットの最長待機時間unit
- timeout 引数の時間単位
InterruptedException
- 現在のスレッドで割り込みが発生した場合
IllegalArgumentException
- パーミットがゼロ未満の場合Thread.interrupt()
public void release(int permits)
指定数のパーミットを解放して、その数だけ利用可能なパーミットを増やします。パーミットの取得を試みる任意のスレッドがある場合、そのうち 1 つのスレッドが選択され、解放されたばかりのパーミットが与えられます。スレッドの要求を満たす数のパーミットがある場合、そのスレッドはスレッドのスケジュール上の目的を有効 (再有効) にします。そうでない場合、スレッドは十分な数のパーミットが利用可能になるまで待機します。このスレッドの要求が満たされた後でもまだ利用可能なパーミットが残っている場合、今度はパーミットの取得を試みる他のスレッドにこれらのパーミットが割り当てられます。
パーミットを解放するスレッドが、acquire
を呼び出してパーミットを取得済みである必要はありません。セマフォの適正な使用法は、アプリケーションのプログラミング規約により確立されます。
permits
- 解放するパーミットの数
IllegalArgumentException
- パーミットがゼロ未満の場合public int availablePermits()
通常、このメソッドはデバッグおよびテスト目的で使用します。
public int drainPermits()
protected void reducePermits(int reduction)
reduction
- 削除するパーミットの数
IllegalArgumentException
- 減らす数が負の場合public boolean isFair()
public final boolean hasQueuedThreads()
public final int getQueueLength()
protected Collection<Thread> getQueuedThreads()
public String toString()
Object
内の toString
|
JavaTM 2 Platform Standard Ed. 5.0 |
|||||||||
前のクラス 次のクラス | フレームあり フレームなし | |||||||||
概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド |
Copyright 2004 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。