CodeGym /Java Blog /ランダム /JavaのWait()メソッド
John Squirrels
レベル 41
San Francisco

JavaのWait()メソッド

ランダム グループに公開済み
この記事では、スレッドを制御するwait()メソッドと、notify() / NoticeAll()メソッドについて説明します。これらのメソッドは基本クラスjava.lang.Objectで定義されているため、Java の継承メカニズムはこれらのメソッドをすべてのクラスに提供します。つまり、独自のクラスとそのオブジェクトを作成するときは、いつでもこれらのメソッドを呼び出すことができます。

wait() メソッドとnotify()/notifyAll() メソッドはどのように機能しますか?

  • wait()。つまり、このメソッドはモニターを解放し、別のスレッドがnotify () / notifyAll()メソッドを呼び出すまで、呼び出しスレッドを待機状態にします。
  • 通知()。wait() メソッドが以前に呼び出されたスレッドの作業を継続します。
  • NoticeAll()メソッドは、以前にwait()メソッドが呼び出されたすべてのスレッドを再開します。
次に、 wait()メソッドを詳しく見てみましょう。Objectクラスは、このメソッドの 3 つのオプションが含まれています。
  • publicfinalnativevoidwait(longtimeoutMillis)はInterruptedExceptionをスローします。これにより、現在のスレッドは起動されるまで待機します。通常、これは通知または中断によって、または一定のリアルタイム時間が経過するまで発生します。

  • public Final void wait() はInterruptedExceptionをスローします。2 番目のメソッドとしてパラメーターなしのメソッドを作成したのは偶然ではありません。実際、そのコードを見ると、メソッドの最初のバリアントを参照しており、引数が 0L であるだけです。

  • パブリック最終待機 (長いタイムアウト、int nanos)。現在のスレッドは、通常は通知や割り込みによってウェイクアップされるまで、または一定のリアルタイム時間が経過するまで待機します。

wait ()メソッドは、呼び出し元のスレッドを一時停止することを目的としています。どういう意味ですか?これらのメソッドはクラスに属します。クラスに基づいてオブジェクトを作成します。オブジェクトはいくつかのスレッドに存在します。つまり、オブジェクトはいくつかのスレッドで作成されます。このオブジェクトが動作するスレッドでwait()を呼び出すと、このスレッドが停止します。オブジェクト自体は一種のモニターとして機能します。それは何ですか?さまざまなオブジェクトを作成でき、それらのすべてにwait()が含まれることは明らかです。方法。どのオブジェクトが特定のスレッドの停止を引き起こしたかを把握できます。スレッドはパラメータに記述されている限り停止し、待機します。そして始まります。このスレッドはそれ自体を開始できません。作業を再開するには、notify メソッドとnotifyAll メソッドがあります。Notice()またはNotifyAll()の呼び出しでは、他のスレッドを実行する必要があります。wait()を使用すると、複数のスレッドを停止し、notifyAll()ですべてのスレッドを開始できます。複数のスレッドが停止され、notify()が呼び出された場合、どのスレッドがこのメソッドを再開するかを正確に知ることは不可能です。wait()メソッドに待機中のスレッドがない場合は、notify()またはNoticeAll()が呼び出されます。スレッドは、現在そのオブジェクトにロックがある場合にのみ、特定のオブジェクトに対してwait()メソッドまたはNotice()メソッドを呼び出すことができます。wait()Notice()、およびNoticeAll() は、同期されたコードからのみ呼び出す必要があります。

Wait() メソッドの例

ここでは、この方法がどのように機能するかを示す最も一般的な例の 1 つを示します。店舗、生産者、消費者がいるとします。メーカーは生産製品の一部を店舗に移し、その後消費者がそれらを手に入れることができます。メーカーがそれぞれ 8 つの商品を生産しなければならないとすると、消費者はそれらをすべて購入しなければなりません。ただし、同時に倉庫に入れることができるアイテムは 6 つまでです。この問題を解決するには、 wait()メソッドとnotify()メソッドを使用します。マーケットメーカークライアントの3 つのクラスを定義しましょう。run()メソッドの製造元、そのメソッドを使用して8 つの製品をMarketオブジェクトに追加します。put()メソッド。クライアントはループ内のrun()メソッドでMarketオブジェクトの get メソッドを呼び出して、これらの商品を取得します。Marketクラスの put メソッドと get メソッドは同期されます。Marketクラス内の商品の存在を追跡するには、item 変数の値をチェックします。製品を取得するget ()メソッドは、製品が少なくとも 1 つある場合にのみ起動する必要があります。そのため、getメソッドでは商品が欠落しているかどうかを確認します。項目が利用できない場合は、wait()メソッドが呼び出されます。このメソッドはMarketオブジェクトのモニターを解放し、 notify()が実行されるまで get メソッドをブロックします。メソッドは同じモニター上で呼び出されます。put()メソッドで項目が追加され、 notify() が呼び出されると、get()メソッドがモニターを取得します。その後、クライアントは商品を受け取ります。これを行うには、メッセージが表示され、項目の値が減ります。最後に、notify()メソッド呼び出しはput()メソッドに続行するよう通知します。put()メソッドでも同様のロジックが機能しますが、Marketに製品が 6 個以下の場合にのみput()メソッドが機能します。

class Market {

   private int item = 0;

   public synchronized void get() {
       //here we use wait() method
       while (item < 1) {
           try {
               wait();
           }
           catch (InterruptedException e) {
           }
       }
       item--;
       System.out.println("A client has bought 1 item...");
       System.out.println("Items quantity in Market warehouse... " + item);
       notify();
   }

   public synchronized void put() {
       //here we use wait() method when the Warehouse is full
       while (item >= 6) {
           try {
               wait();
           }
           catch (InterruptedException e) {
           }
       }
       item ++;
       System.out.println("Manufacturer has added 1 more item...");
       System.out.println("Now there are " + item + " items in Warehouse" );
       notify();
   }
}

class Manufacturer implements Runnable {

   Market market;

   Manufacturer(Market market) {
       this.market = market;
   }


   public void run() {
       for (int i = 0; i < 8; i++) {
           market.put();
       }
   }
}

class Client implements Runnable {

   Market market;
   Client(Market market) {
       this.market = market;
   }
   public void run() {
       for (int i = 0; i < 8; i++) {
           market.get();
       }
   }
}
//wait() method test class
public class WaitTest {
   public static void main(String[] args) {

       Market market = new Market();
       Manufacturer manufacturer = new Manufacturer(market);
       Client client = new Client(market);
       new Thread(manufacturer).start();
       new Thread(client).start();
   }
}
ここでは、get()メソッドでwait()を使用して、メーカーが新しいアイテムを追加するのを待っています。そして、追加した後、 Warehouse上の 1 つの場所が空になり、さらに追加できるかのように、 Notice()を呼び出します。put()メソッドでは、wait()を使用して、 Warehouse上のスペースが解放されるのを待ちます。スペースが空いた後、アイテムを追加し、notify() がスレッドを開始し、クライアントがアイテムを取得できるようになります。プログラムの出力は次のとおりです。
メーカーはさらに 1 つのアイテムを追加しました... 現在、倉庫に 1 つのアイテムがあります メーカーはさらに 1 つのアイテムを追加しています... 現在、倉庫に 2 つのアイテムがあります メーカーはさらに 1 つのアイテムを追加しています... 現在、倉庫に 3 つのアイテムがあります メーカーはさらに 1 つのアイテムを追加しました... 現在、倉庫に 4 つのアイテムがあります メーカーがさらに 1 つのアイテムを追加しました... 現在、倉庫に 5 つのアイテムがあります メーカーがさらに 1 つのアイテムを追加しました... 現在、倉庫に 6 つのアイテムがあります クライアントが購入しました1 つのアイテム... マーケット倉庫のアイテム数量... 5 クライアントが 1 つのアイテムを購入しました... マーケット ウェアハウスのアイテム数量... 4 クライアントが 1 つのアイテムを購入しました... マーケット ウェアハウスのアイテム数量... 3クライアントが 1 つのアイテムを購入しました... マーケット ウェアハウスのアイテム数量... 2 クライアントが 1 つのアイテムを購入しました... マーケット ウェアハウスのアイテム数量... 1 クライアントが 1 つのアイテムを購入しました... マーケット ウェアハウスのアイテム数量...0 メーカーがさらに 1 つのアイテムを追加しました... 現在、倉庫に 1 つのアイテムがあります メーカーがさらに 1 つのアイテムを追加しています... 現在、倉庫に 2 つのアイテムがあります クライアントが 1 つのアイテムを購入しました... マーケット倉庫のアイテム数量... 1 クライアントが 1 つのアイテムを購入しました... マーケット倉庫内のアイテム数量... 0 プロセスは終了コード 0 で終了しました
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION