この記事では、スレッドを制御するwait()メソッドと、notify() / NoticeAll()メソッドについて説明します。これらのメソッドは基本クラスjava.lang.Objectで定義されているため、Java の継承メカニズムはこれらのメソッドをすべてのクラスに提供します。つまり、独自のクラスとそのオブジェクトを作成するときは、いつでもこれらのメソッドを呼び出すことができます。
ここでは、get()メソッドでwait()を使用して、メーカーが新しいアイテムを追加するのを待っています。そして、追加した後、 Warehouse上の 1 つの場所が空になり、さらに追加できるかのように、 Notice()を呼び出します。put()メソッドでは、wait()を使用して、 Warehouse上のスペースが解放されるのを待ちます。スペースが空いた後、アイテムを追加し、notify() がスレッドを開始し、クライアントがアイテムを取得できるようになります。プログラムの出力は次のとおりです。
wait() メソッドとnotify()/notifyAll() メソッドはどのように機能しますか?
- wait()。つまり、このメソッドはモニターを解放し、別のスレッドがnotify () / notifyAll()メソッドを呼び出すまで、呼び出しスレッドを待機状態にします。
- 通知()。wait() メソッドが以前に呼び出されたスレッドの作業を継続します。
- NoticeAll()メソッドは、以前にwait()メソッドが呼び出されたすべてのスレッドを再開します。
-
publicfinalnativevoidwait(longtimeoutMillis)はInterruptedExceptionをスローします。これにより、現在のスレッドは起動されるまで待機します。通常、これは通知または中断によって、または一定のリアルタイム時間が経過するまで発生します。
-
public Final void wait() はInterruptedExceptionをスローします。2 番目のメソッドとしてパラメーターなしのメソッドを作成したのは偶然ではありません。実際、そのコードを見ると、メソッドの最初のバリアントを参照しており、引数が 0L であるだけです。
-
パブリック最終待機 (長いタイムアウト、int nanos)。現在のスレッドは、通常は通知や割り込みによってウェイクアップされるまで、または一定のリアルタイム時間が経過するまで待機します。
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();
}
}
メーカーはさらに 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 で終了しました
GO TO FULL VERSION