这两个方法被定义在Object类上
//调用该方法的线程会进入WAITING状态,只有等待其他线程的通知或被中断才会返回
public final void wait() throws InterruptedException
//通知一个在对象上等待的线程,使其从wait()方法返回,当然返回的前提是该线程获取到了对象的锁
public final native void notify()
当一个对象实例调用wait()方法后,当前线程就会在这个对象上等待,直到其他线程调用了notify()方法为止。
wait()与sleep()的不同:
相同点在于两者都可以让线程等待若干时间,而wait()方法会释放目标对象的锁,sleep()不会释放任何资源
wait()和notify()具体的工作过程
- 第一步:线程A(取得object监视器 → object.wait() → 释放object监视器)
- 第二步:线程B(取得object监视器 → object.notify() → 释放object监视器)
- 第三步:线程A(等待object监视器 → 重获object监视器 → 继续执行)
值得注意的几点
- 线程调用了object.wait(),那么它就会进入object对象的等待队列,这个等待队列中,可能会有多个线程同时等待某一对象。
- object.notify()被调用时,系统会从object对象的等待队列中,随机选择一个线程,并将其唤醒(不公平的,随机选择)。object.notify()方法则会唤醒在这个等待队列中所有等待的线程,而不是随机选择一个。
- object.wait()并不是可以随便调用,它必须包含在对象的synchronized语句中,因为无论是wait()还是notify()都需要首先获得目标对象的一个监视器。
/**
* wait() 和 notify()使用案例
* @author MatrixOne001
*
*/
public class SimpleWN {
public static Object object = new Object();
public static class WThread extends Thread{
@Override
public void run() {
synchronized (object) {
try {
System.out.println( "WThread wait for object");
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( "WThread end");
}
}
}
public static class NThread extends Thread{
@Override
public void run() {
synchronized (object) {
try {
System.out.println( "NThread notify for object");
object.notify();
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( "NThread end");
}
}
}
}
以上的代码稍加修改,就是等待/通知的经典范式
等待方(消费者)的伪代码:
//1.获取对象的锁
synchronized( 对象 ){
// 2.如果条件不满足,那么调用对象的wait(),被通知后仍要检查条件
while( 条件不满足 ){
对象.wait();
}
//3.条件满足则执行对应的逻辑
对象的处理逻辑
}
通知方(生产者)的伪代码
//1.获得对象的锁
synchronized( 对象 ){
// 2.改变条件
改变条件..
//3.发送通知
对象.notify(); // 或 对象.notifyAll();
}