JavaTM 2 Platform
Standard Ed. 5.0

java.util.concurrent
クラス Semaphore

java.lang.Object
  上位を拡張 java.util.concurrent.Semaphore
すべての実装されたインタフェース:
Serializable

public class Semaphore
extends Object
implements Serializable

カウントに使用されるセマフォ。概念的には、セマフォは許可セットを管理します。各 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 に設定せずにこれらのメソッドを使用する場合、無制限に延期される危険が増すことに留意してください。

導入されたバージョン:
1.5
関連項目:
直列化された形式

コンストラクタの概要
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
 

コンストラクタの詳細

Semaphore

public Semaphore(int permits)
指定された数のパーミットおよび非均等設定を使用して Semaphore を作成します。

パラメータ:
permits - 使用可能なパーミットの初期数。これは負の値にすることもできます。値が負の場合、どの取得が許可されるよりも前に解放を行う必要があります。

Semaphore

public Semaphore(int permits,
                 boolean fair)
指定数のパーミットおよび指定された均等設定を使用して Semaphore を作成します。

パラメータ:
permits - 使用可能なパーミットの初期数。これは負の値にすることもできます。値が負の場合、どの取得が許可されるよりも前に解放を行う必要があります。
fair - 競合の発生時にこのセマフォが先入れ先出しのパーミット許可を保証する場合は true、そうでない場合は false
メソッドの詳細

acquire

public void acquire()
             throws InterruptedException
このセマフォからパーミットを取得し、利用可能になるまでブロックを実行します。それ以外の場合、スレッドで割り込みが発生します。

パーミットが利用可能な場合はそれを取得してただちに復帰し、利用可能なパーミットの数を 1 つ減らします。

パーミットを利用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 2 つのいずれかが起きるまで待機します。

現在のスレッドで、

InterruptedException がスローされ、現在のスレッドの割り込みステータスがクリアされます。

例外:
InterruptedException - 現在のスレッドで割り込みが発生した場合
関連項目:
Thread.interrupt()

acquireUninterruptibly

public void acquireUninterruptibly()
このセマフォからパーミットを取得します。パーミットが利用可能になるまでブロックを実行します。

パーミットが利用可能な場合はそれを取得してただちに復帰し、利用可能なパーミットの数を 1 つ減らします。

パーミットを利用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、他のスレッドがこのセマフォに対して release() メソッドを呼び出し、次にパーミットを割り当てられるのが現在のスレッドになるまで待機します。

パーミットの待機中に現在のスレッドで割り込みが発生した場合、待機は続行されますが、スレッドがパーミットを割り当てられる時は、パーミットで割り込みが発生しなかった場合に受け取る時とは異なる場合があります。スレッドがメソッドから復帰する際に、割り込み状態が設定されます。


tryAcquire

public boolean tryAcquire()
呼び出し時にパーミットが利用可能である場合にのみ、このセマフォからパーミットを取得します。

パーミットが利用可能な場合はそれを取得し、値 true でただちに復帰して、利用可能なパーミットの数を 1 つ減らします。

パーミットを利用できない場合、このメソッドは値 false でただちに復帰します。

このセマフォが均等順序付けポリシーを使用するように設定されている場合でも、パーミットが利用可能であれば、他のスレッドが現在、待機中であるかどうかに関係なく、tryAcquire() の呼び出しによりただちにそれを取得します。この「バージング」動作は、均等性を損なうとしても、特定の状況で有用なものになります。均等設定を重視する場合、ほぼ等価な tryAcquire(0, TimeUnit.SECONDS) を使用してください (これも割り込みを検出する)。

戻り値:
パーミットが取得された場合は true、そうでない場合は false

tryAcquire

public boolean tryAcquire(long timeout,
                          TimeUnit unit)
                   throws InterruptedException
指定された待機時間内にパーミットが利用可能になり、現在のスレッドで割り込みが発生していない場合に、このセマフォからパーミットを取得します。

パーミットが利用可能な場合はそれを取得し、値 true でただちに復帰して、利用可能なパーミットの数を 1 つ減らします。

パーミットを利用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 3 つのいずれかが起きるまで待機します。

パーミットが取得されると、値 true が返されます。

現在のスレッドで、

InterruptedException がスローされ、現在のスレッドの割り込みステータスがクリアされます。

指定された待機時間が経過すると、値 false が返されます。時間がゼロまたはそれより小さい場合、メソッドは待機しません。

パラメータ:
timeout - パーミットの最長待機時間
unit - timeout 引数の時間単位
戻り値:
パーミットが取得された場合は true、パーミットが取得される前に待機時間が経過した場合は false
例外:
InterruptedException - 現在のスレッドで割り込みが発生した場合
関連項目:
Thread.interrupt()

release

public void release()
パーミットを解放してセマフォに返します。

パーミットを解放し、利用可能なパーミットの数を 1 増やします。いずれかのスレッドがパーミットの取得を試みる場合、それが選択され、解放されたばかりのパーミットが与えられます。そのスレッドは、スレッドスケジューリングに関して再度有効にされます。

パーミットを解放するスレッドが、acquire() を呼び出してパーミットを取得済みである必要はありません。セマフォの適正な使用法は、アプリケーションのプログラミング規約により確立されます。


acquire

public void acquire(int permits)
             throws InterruptedException
このセマフォから指定数のパーミットを取得し、すべてが利用可能になるまでブロックを実行します。それ以外の場合、スレッドで割り込みが発生します。

指定数のパーミットが利用可能な場合にそれを取得し、ただちに復帰して、利用可能なパーミットの数を指定数だけ減らします。

利用可能なパーミットの数が不足している場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 2 つのいずれかが起きるまで待機します。

現在のスレッドで、

InterruptedException がスローされ、現在のスレッドの割り込み状態がクリアされます。このスレッドに割り当てられるはずのパーミットは、release() の呼び出しで利用可能になったかのように、パーミットの取得を試みる他のスレッドに割り当てられます。

パラメータ:
permits - 取得するパーミットの数
例外:
InterruptedException - 現在のスレッドで割り込みが発生した場合
IllegalArgumentException - パーミットがゼロ未満の場合
関連項目:
Thread.interrupt()

acquireUninterruptibly

public void acquireUninterruptibly(int permits)
指定数のパーミットをこのセマフォから取得し、すべてが利用可能になるまでブロックします。

指定数のパーミットが利用可能な場合にそれを取得し、ただちに復帰して、利用可能なパーミットの数を指定数だけ減らします。

十分な数のパーミットを利用できない場合、現在のスレッドはスレッドのスケジューリングに関して無効になります。その後、他のスレッドがこのセマフォに対して release メソッドのいずれかを呼び出し、次回パーミットを割り当てられるのが現在のスレッドで、利用可能なパーミットの数がこの要求を満たすまで待機します。

パーミットの待機中に現在のスレッドで割り込みが発生する場合、待機は継続され、キュー内の位置は影響を受けません。スレッドがこのメソッドから復帰する際、割り込み状態が設定されます。

パラメータ:
permits - 取得するパーミットの数
例外:
IllegalArgumentException - パーミットがゼロ未満の場合

tryAcquire

public boolean tryAcquire(int permits)
呼び出し時に指定数のパーミットをすべて利用可能な場合にのみ、パーミットをこのセマフォから取得します。

指定数のパーミットが利用可能な場合にそれを取得し、ただちに true で復帰して、利用可能なパーミットの数を指定数だけ減らします。

利用可能なパーミットの数が不十分な場合、このメソッドは値 false でただちに復帰します。利用可能なパーミットの数は変化しません。

このセマフォが均等順序付けポリシーを使用するように設定されている場合でも、パーミットが利用可能であれば、他のスレッドが待機中であるかどうかに関係なく、tryAcquire の呼び出しによりただちにそれを取得します。この「バージング」動作は、均等性を損なうとしても、特定の状況で有用なものになります。均等設定を重視する場合、ほぼ等価な tryAcquire(permits, 0, TimeUnit.SECONDS) を使用してください (これも割り込みを検出する)。

パラメータ:
permits - 取得するパーミットの数
戻り値:
パーミットが取得された場合は true、そうでない場合は false
例外:
IllegalArgumentException - パーミットがゼロ未満の場合

tryAcquire

public boolean tryAcquire(int permits,
                          long timeout,
                          TimeUnit unit)
                   throws InterruptedException
指定された待機時間内に指定数のパーミットがすべて利用可能になり、現在のスレッドで割り込みが発生していない場合に、それらのパーミットをこのセマフォから取得します。

指定数のパーミットが利用可能な場合にそれを取得し、ただちに値 true で復帰して、利用可能なパーミットの数を指定数だけ減らします。

利用可能なパーミットの数が不足している場合、現在のスレッドはスレッドのスケジューリングに関して無効になり、次の 3 つのいずれかが起きるまで待機します。

パーミットが取得されると、値 true が返されます。

現在のスレッドで、

InterruptedException がスローされ、現在のスレッドの割り込み状態がクリアされます。このスレッドに割り当てられるはずのパーミットは、release() の呼び出しで利用可能になったかのように、パーミットの取得を試みる他のスレッドに割り当てられます。

指定された待機時間が経過すると、値 false が返されます。時間がゼロ以下の場合、メソッドは待機しません。このスレッドに割り当てられるはずのパーミットはすべて、release() の呼び出しにより利用可能にされたかのように、パーミットの取得を試みる他のスレッドに代わりに割り当てられます。

パラメータ:
permits - 取得するパーミットの数
timeout - パーミットの最長待機時間
unit - timeout 引数の時間単位
戻り値:
すべてのパーミットが取得された場合は true、すべてのパーミットが取得される前に待機時間が経過した場合は false
例外:
InterruptedException - 現在のスレッドで割り込みが発生した場合
IllegalArgumentException - パーミットがゼロ未満の場合
関連項目:
Thread.interrupt()

release

public void release(int permits)
指定数のパーミットを解放して、セマフォに返します。

指定数のパーミットを解放して、その数だけ利用可能なパーミットを増やします。パーミットの取得を試みる任意のスレッドがある場合、そのうち 1 つのスレッドが選択され、解放されたばかりのパーミットが与えられます。スレッドの要求を満たす数のパーミットがある場合、そのスレッドはスレッドのスケジュール上の目的を有効 (再有効) にします。そうでない場合、スレッドは十分な数のパーミットが利用可能になるまで待機します。このスレッドの要求が満たされた後でもまだ利用可能なパーミットが残っている場合、今度はパーミットの取得を試みる他のスレッドにこれらのパーミットが割り当てられます。

パーミットを解放するスレッドが、acquire を呼び出してパーミットを取得済みである必要はありません。セマフォの適正な使用法は、アプリケーションのプログラミング規約により確立されます。

パラメータ:
permits - 解放するパーミットの数
例外:
IllegalArgumentException - パーミットがゼロ未満の場合

availablePermits

public int availablePermits()
このセマフォで利用可能な現在のパーミット数を返します。

通常、このメソッドはデバッグおよびテスト目的で使用します。

戻り値:
このセマフォで利用可能なパーミットの数

drainPermits

public int drainPermits()
すぐに利用可能なパーミットをすべて取得して返す

戻り値:
パーミットの数

reducePermits

protected void reducePermits(int reduction)
利用可能なパーミットの数を、指定された数だけ減らします。このメソッドは、セマフォを使用して利用不可になったリソースを追跡するサブクラスで有用です。このメソッドは、パーミットが利用可能になるまでの待機をブロックしないという点で、acquire と異なります。

パラメータ:
reduction - 削除するパーミットの数
例外:
IllegalArgumentException - 減らす数が負の場合

isFair

public boolean isFair()
このセマフォで均等性が true に設定されている場合は true を返します。

戻り値:
このセマフォで均等性が true に設定されている場合は true

hasQueuedThreads

public final boolean hasQueuedThreads()
取得を待機中のスレッドが存在するかどうかを照会します。取り消しはいつでも発生する可能性があるため、true が返されても、他のいずれかのスレッドが取得することは保証されていません。このメソッドは、主にシステム状態の監視に使用する目的で設計されています。

戻り値:
ロックの取得を待機中の他のスレッドが存在する可能性がある場合は true

getQueueLength

public final int getQueueLength()
取得を待機中のスレッドの推定数を返します。このメソッドが内部のデータ構造をトラバースしている間にも、スレッド数が動的に変化する場合があるため、この値は推定に過ぎません。このメソッドは、同期の制御用ではなく、システム状態を監視するためのものです。

戻り値:
このロックを待機しているスレッドの推定数

getQueuedThreads

protected Collection<Thread> getQueuedThreads()
取得を待機しているスレッドを含むコレクションを返します。実際のスレッドセットは、結果の構築中にも動的に変化する可能性があるため、返されるコレクションは最善の努力を払った上での推定に過ぎません。返されるコレクションの要素には、特定の順序は存在しません。このメソッドは、より包括的な監視機能を提供するサブクラスの構築を容易にする目的で設計されています。

戻り値:
スレッドのコレクション

toString

public String toString()
このセマフォおよびその状態を識別する文字列を返します。状態は括弧で囲まれ、文字列「Permits =」に続いてパーミットの数が指定されます。

オーバーライド:
クラス Object 内の toString
戻り値:
このセマフォおよびその状態を識別する文字列

JavaTM 2 Platform
Standard Ed. 5.0

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

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