JavaのObjectクラスには、リソースのロック状態に関するスレッド間の通信を可能にする3つの最終メソッドが含まれています。これらのメソッドはwait()、notify()、およびnotifyAll()です。したがって、今日はJavaプログラム内のwait、notify、およびnotifyAllを見てみましょう。
Javaでのwait、notify、およびnotifyAll
これらのメソッドをオブジェクト上で呼び出す現在のスレッドは、オブジェクトモニターを持っている必要があります。それ以外の場合はjava.lang.IllegalMonitorStateException例外がスローされます。
wait
Objectのwaitメソッドには3つのバリアントがあり、1つは他のスレッドがオブジェクト上でnotifyまたはnotifyAllメソッドを呼び出すのを無期限に待機し、現在のスレッドを起こすものです。他の2つのバリアントは、指定された時間だけ現在のスレッドを待機させます。
notify
notify メソッドは、オブジェクトで待機しているスレッドのうち、1つだけを起動し、そのスレッドが実行を開始します。したがって、複数のスレッドがオブジェクトを待っている場合、このメソッドはそのうちの1つだけを起動します。起動するスレッドの選択は、OS のスレッド管理の実装に依存します。
notifyAll
notifyAll メソッドは、オブジェクトで待機しているすべてのスレッドを起動しますが、どのスレッドが最初に処理されるかは、OS の実装に依存します。これらのメソッドは、生産者消費者問題を実装するために使用できます。ここでは、待機中のスレッドにオブジェクトを通知するときに、消費者スレッドがキュー内のオブジェクトを待機し、生産者スレッドがキューにオブジェクトを配置し、待機中のスレッドに通知する方法を示します。同じオブジェクトで複数のスレッドが作業する例を見てみましょう。そして、wait、notify、notifyAll メソッドを使用します。
Message
A java bean class on which threads will work and call wait and notify methods.
package com.journaldev.concurrency;
public class Message {
private String msg;
public Message(String str){
this.msg=str;
}
public String getMsg() {
return msg;
}
public void setMsg(String str) {
this.msg=str;
}
}
Waiter
A class that will wait for other threads to invoke notify methods to complete it’s processing. Notice that Waiter thread is owning monitor on Message object using synchronized block.
package com.journaldev.concurrency;
public class Waiter implements Runnable{
private Message msg;
public Waiter(Message m){
this.msg=m;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
synchronized (msg) {
try{
System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
//メッセージを処理します。
System.out.println(name+" processed: "+msg.getMsg());
}
}
}
通知者
A class that will process on Message object and then invoke notify method to wake up threads waiting for Message object. Notice that synchronized block is used to own the monitor of Message object.
package com.journaldev.concurrency;
public class Notifier implements Runnable {
private Message msg;
public Notifier(Message msg) {
this.msg = msg;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+" started");
try {
Thread.sleep(1000);
synchronized (msg) {
msg.setMsg(name+" Notifier work done");
msg.notify();
// msg.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
WaitNotifyTest
複数のWaiterとNotifierのスレッドを作成し、それらを開始するテストクラス。
package com.journaldev.concurrency;
public class WaitNotifyTest {
public static void main(String[] args) {
Message msg = new Message("process it");
Waiter waiter = new Waiter(msg);
new Thread(waiter,"waiter").start();
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1, "waiter1").start();
Notifier notifier = new Notifier(msg);
new Thread(notifier, "notifier").start();
System.out.println("All the threads are started");
}
}
上記のプログラムを呼び出すと、以下の出力が表示されますが、プログラムは完了しません。なぜなら、メッセージオブジェクトに対して待機しているスレッドが2つあり、notify()メソッドがそれらのうちの1つだけを起こしており、もう1つのスレッドはまだ通知を待っているからです。
waiter waiting to get notified at time:1356318734009
waiter1 waiting to get notified at time:1356318734010
All the threads are started
notifier started
waiter waiter thread got notified at time:1356318735011
waiter processed: notifier Notifier work done
Notifierクラスでnotify()呼び出しをコメントアウトし、notifyAll()呼び出しをコメント解除すると、以下のような出力が生成されます。
waiter waiting to get notified at time:1356318917118
waiter1 waiting to get notified at time:1356318917118
All the threads are started
notifier started
waiter1 waiter thread got notified at time:1356318918120
waiter1 processed: notifier Notifier work done
waiter waiter thread got notified at time:1356318918120
waiter processed: notifier Notifier work done
notifyAll()メソッドは両方のWaiterスレッドを起こし、プログラムは実行後に完了して終了します。これでJavaでのwait、notify、およびnotifyAllについては以上です。
Source:
https://www.digitalocean.com/community/tutorials/java-thread-wait-notify-and-notifyall-example