Java のセマフォは、いつでも共有リソースにアクセスできるスレッドの数を制限する同期補助機能です。これは java.util.concurrent パッケージの一部であり、ファイル、データベース、ネットワーク接続などのリソースへの同時アクセスを管理するために使用されます。
セマフォは、設定された数の許可へのアクセスを制御します。各許可は、特定のリソースにアクセスする権利を表します。セマフォは、使用可能な許可の数を追跡し、リソースに同時にアクセスできるスレッドの数を決定します。
Permit : スレッドが共有リソースへのアクセスを続行できるようにするトークンまたはチケット。
セマフォを作成するときは、使用可能な許可の数を指定します。この数値は、リソースに同時にアクセスできるスレッドの数を定義します。
スレッドがリソースにアクセスするには、セマフォから許可を取得する必要があります。これは、acquire() メソッドを使用して行われます。
Acquire : このメソッドは、スレッドがリソースにアクセスしたいときに呼び出されます。許可が利用可能な場合、セマフォは利用可能な許可の数を減らし、スレッドの続行を許可します。使用可能な許可がない場合、スレッドは許可が使用可能になるまでブロックされます。
ブロック動作 : 利用可能な許可がない場合、acquire() を呼び出すスレッドは、別のスレッドが許可を解放するまでブロックされます (つまり、待機します)。
スレッドがリソースの使用を終了したら、許可を解放して他のスレッドが使用できるようにする必要があります。これは、release() メソッドを使用して行われます。
Release : このメソッドは、利用可能な許可の数を増やします。許可を待っているスレッドがある場合、そのうちの 1 つがブロック解除され、許可を取得できるようになります。
Java には 2 種類のセマフォがあります:
セマフォがどのように機能するかをより深く理解するために、実際の実装を見てみましょう。複数のスレッドが限られたリソースにアクセスしようとする単純なシナリオを作成します。
import java.util.concurrent.Semaphore; public class SemaphoreDemo { // Creating a semaphore with 3 permits private static final Semaphore semaphore = new Semaphore(3); public static void main(String[] args) { // Creating and starting 6 threads for (int i = 1; i <= 6; i++) { new WorkerThread("Worker " + i).start(); } } static class WorkerThread extends Thread { private String name; WorkerThread(String name) { this.name = name; } @Override public void run() { try { System.out.println(name + " is trying to acquire a permit..."); // Acquiring the semaphore semaphore.acquire(); System.out.println(name + " acquired a permit."); // Simulating work by sleeping Thread.sleep(2000); System.out.println(name + " is releasing a permit."); } catch (InterruptedException e) { e.printStackTrace(); } finally { // Releasing the semaphore semaphore.release(); } } } }
この例では、3 つの許可を持つセマフォを作成します。これは、常に 3 つのスレッドのみがコードのクリティカル セクションにアクセスできることを意味します。次に、6 つのスレッドを作成し、そのすべてが許可の取得を試みます。スレッドが許可を取得すると、許可を解放する前に 2 秒間スリープして一部の作業をシミュレートします。
上記のコードを実行すると、出力は次のようになります:
Worker 1 is trying to acquire a permit... Worker 1 acquired a permit. Worker 2 is trying to acquire a permit... Worker 2 acquired a permit. Worker 3 is trying to acquire a permit... Worker 3 acquired a permit. Worker 4 is trying to acquire a permit... Worker 5 is trying to acquire a permit... Worker 6 is trying to acquire a permit... Worker 1 is releasing a permit. Worker 4 acquired a permit. Worker 2 is releasing a permit. Worker 5 acquired a permit. Worker 3 is releasing a permit. Worker 6 acquired a permit.
ここでは、最初の 3 つのスレッドが許可を正常に取得し、タスクを開始します。残りのスレッドは、許可が解放されるまで待機してから続行する必要があります。
セマフォは、次のような特定のリソースへの同時アクセス数を制限する必要があるシナリオで特に役立ちます。
3.1 利点
柔軟性 : セマフォを使用すると、複数のスレッドによるリソース アクセスを正確に制御できます。
スケーラビリティ : セマフォを使用すると、多数のリソースへのアクセスを簡単に管理できます。
公平性 : スレッドが公平な方法で許可を取得できるようにセマフォを構成できます。
3.2 欠点複雑さ : セマフォを使用するとコードが複雑になり、デバッグが困難になる可能性があります。
デッドロック : セマフォが正しく処理されないと、スレッドが許可を待って無期限にブロックされるデッドロックが発生する可能性があります。
4. Java でセマフォを使用するためのベスト プラクティス無期限にブロックするacquire()を使用する代わりに、tryAcquire()を使用してタイムアウト付きで許可の取得を試みることができます。これにより、スレッドが待機状態になるのを防ぎます。
import java.util.concurrent.Semaphore; public class SemaphoreDemo { // Creating a semaphore with 3 permits private static final Semaphore semaphore = new Semaphore(3); public static void main(String[] args) { // Creating and starting 6 threads for (int i = 1; i <= 6; i++) { new WorkerThread("Worker " + i).start(); } } static class WorkerThread extends Thread { private String name; WorkerThread(String name) { this.name = name; } @Override public void run() { try { System.out.println(name + " is trying to acquire a permit..."); // Acquiring the semaphore semaphore.acquire(); System.out.println(name + " acquired a permit."); // Simulating work by sleeping Thread.sleep(2000); System.out.println(name + " is releasing a permit."); } catch (InterruptedException e) { e.printStackTrace(); } finally { // Releasing the semaphore semaphore.release(); } } } }
リソースのリークを避けるために、常に finally ブロックで許可を解放してください。これにより、例外が発生した場合でも許可が確実に解除されます。
単一スレッドのリソースのロックとロック解除のみが必要な場合は、バイナリ セマフォの代わりに ReentrantLock または synchronized の使用を検討してください。
セマフォは Java で同時実行性を管理するための強力なツールであり、共有リソースにアクセスするスレッドの数を制御できます。この記事で説明する手法とベスト プラクティスに従うことで、Java アプリケーションにセマフォを効果的に実装して、安全かつ効率的なリソース管理を確保できます。
ご質問がある場合、またはセマフォに関するご自身の経験を共有したい場合は、お気軽に以下にコメントしてください。
詳細については、 で投稿をご覧ください: セマフォを使用して Java で同時実行性を管理するテクニック
以上がセマフォを使用して Java で同時実行性を管理する手法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。