参考书籍:
java并发编程的艺术
等待/通知的相关方法
方法名称 | 描述 |
---|---|
notify() | 通知一个在对象上等待的线程,由WAITING状态变为BLOCKING状态,从等待队列移动到同步队列,等待CPU调度获取该对象的锁,当该线程获取到了对象的锁后,该线程从wait()方法返回 |
notifyAll() | 通知所有等待在该对象上的线程,由WAITING状态变为BLOCKING状态,等待CPU调度获取该对象的锁 |
wait() | 调用该方法的线程进入WAITING状态,并将当前线程放置到对象的等待队列,只有等待另外线程的通知或被中断才会返回,需要注意,调用wait()方法后,会释放对象的锁 |
wait(long) | 超时等待一段时间,这里的参数时间是毫秒,也就是等待长达n毫秒,如果没有通知就超时返回 |
wait(long,int) | 对于超时时间更细力度的控制,可以达到纳秒 |
注意:以上方法必须首先获得该对象的锁后才能调用,否则会抛出IllegalMonitorStateException
Throws:
IllegalMonitorStateException - if the current thread is not the owner of this object's monitor.
等待通知机制,是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B调用了对象O的notify()或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,进而执行后续操作。上述两个线程通过对象O来完成交互,而对象上的wait()和notify/notifyAll()的关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作。
public class WaitNotify{
static boolean flag = true;//不需要为volatile,因为对于flag的操作均在synchronized锁的保护下进行,可以保证flag的内存可见性
static Object lock = new Object();
public static void main(String args[]) throws Exception{
Thread waitThread = new Thread(new Wait(),"WaitThread");
waitThread.start();
TimeUnit.SECONDS.sleep(1);//1 second -> package java.util.cocurrent
Thread notifyThread = new Thread(new Notify(),"NotifyThread");
notifyThread.start();
}
static class Wait implements Runnable{
public void run(){
//加锁,拥有lock的monitor
synchronized(lock){
//当条件不满足时,继续wait,同时释放了lock的锁
while(flag){
try{
System.out.println("flag is ture, Wait");
lock.wait();
}catch(InterruptedException e){
//除了notify通知,带超时的wait()方法、线程中断机制也能唤醒此线程
}
}
System.out.println("flag is false,complete");
}
}
}
static class Notify implements Runnable{
public void run(){
synchronized(lock){
//获取lock的锁,然后进行通知,通知时不会释放lock的锁,直到当前线程释放了lock,调用了notifyAll,并且WaitThread获得了锁之后,wait线程才能从wait()方法返回
System.out.println("Notify get lock ,begin notify");
lock.notifyAll();
flag = false;
TimeUnit.SECONDS.sleep(5);
}
synchronized(lock){
System.out.println("Notify get lock again");
}
}
}
}