在java类的对象中包含了三个方法,允许进程间相互通知锁定状态的资源。这三个方法是wait(),notify()和notifyAll();
任何一个调用这些方法的对象都必须持有该对象的一个对象锁,否则的话,会抛出java.lang.IllegalMonitorStateException异常
Wait
wait方法有三个状态的变化。一个是无限期的等待任何一个线程来调用所持有的对象的notify或者是notifyAll 方法来唤醒当前线程。另外两个变化是将当前的线程等待特定的时间再到唤醒状态
Notify
notify方法只会唤醒一个处于等待状态的该对象,然后是对应的线程开始继续运行。因此,当一个对象有很多歌线程处于等待状态的时候,这个方法只会唤醒他们其中的一个。至于唤醒哪一个,这就取决于操作系统的线程管理了。
notifyAll
该方法会唤醒对象的所有的处于等待状态的线程。哪一个先处理这同样取决于操作系统
这些方法可以被用到生产消费者问题上。消费者线程一是在队列中一直处于等待状态,而生产者则是往队列中放入对象,并且通知消费者。
下面是一个例子,有多个线程工作在同一个对象上。
Message
一个java bean类,我们让线程工作在这个对象的wait和notfify方法上
Message.java
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
该类将会等待其他的线程来调用notify方法来继续完成该线程的处理工作。需要注意的是,该waiter对象是拥有一个对象message的锁的,因为它使用了同步块
Waiter.java
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());
}
}
}
Notifier
该方法将会处理message对象,并调用notify方法来唤醒message对象正在等待的线程。和wiater一样,利用同步块来获取该对象的锁
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
测试类,该类将创建对个线程并且启动他们
WaitNotifyTest.java
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");
}
}
执行上面的测试类,将会看到下面的输出。因为对象 msg有两个等待的线程,而调用了notify方法,只唤醒了他们其中的一个,另外一个还在继续等待被唤醒。
notify()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
当打开注释,并且将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()方法会唤醒所有的处于等待状态的线程让他们执行没有完成的工作
原文:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example