java.lang.Object
类提供了一套等待/通知的 API,它由 3 个 wait()、一个 notify() 和一个 notifyAll() 方法组成。wait() 方法等待某个条件成立,当这个条件成立时,notify() 和 notifyAll() 方法通知处于等待中的线程。
void wait()
:导致当前线程一直处于等待,直到另外的线程调用这个对象的 notify()
或者 notifyAll()
方法,又或者一直等待其他的线程中断当前等待的线程。void wait(long timeout)
:其他定义和 void wait()
一致,多了等待特定的毫秒数(由 timeout 确定)。当 timeout 是负数的时候,这个方法抛出 java.lang.IllegalArgumentException
。void wait(long timeout, int nanos)
:其他定义和 void wait()
一致,多了等待特定的毫秒(由 timeout 确定)和纳秒数(由 nanos 确定)。当 timeout 是负数、nanos 是负数、或者 nanos 大于 999999 的时候,这个方法抛出 java.lang.IllegalArgumentException
。void notify()
:唤醒正在等待该对象监听器的单条线程。如果有几条线程在该对象上等待,其中某一条会被挑选出来唤醒,这种选择是随意的且取决于具体实现。void notifyAll()
:唤醒正在等待该对象监听器的全部线程。注意:
wait()
方法都会抛出 java.lang.InterruptedException
。wait()
、notify()
和 notifyAll()
方法。(防止出现 lost-wake-up 问题)notify()
方法,否则使用 notifyAll()
方法。为了避免使用者出现 "Lost-Wake-Up" 问题。
关于什么是 "Lost-Wait-Up" 问题,可以参考狼叔的博客:
https://www.jianshu.com/p/b8073a6ce1c0
总结如下
wait()
/ notify()
调用必须要在一个同步块中,,就是不想让我们在不经意间出现这种 lost wake up问题。java.util.concurrent.locks.Condition
的 await()
/ signal()
也必须要在同步块中如下述代码,加锁的是 obj 对象,notify 却是 anotherObj 对象使用,会抛出 IllegalMonitorStateException 异常。
private Object obj = new Object();
private Object anotherObj = new Object();
@Test
public void produce() {
synchronized (obj) {
try {
anotherObj.notify();
} catch (Exception e) {
e.printStackTrace();
}
}
}