IllegalMonitorStateException异常,我们先看下API的定义:
/**
* Thrown to indicate that a thread has attempted to wait on an
* object's monitor or to notify other threads waiting on an object's
* monitor without owning the specified monitor.
*
* @author unascribed
* @see java.lang.Object#notify()
* @see java.lang.Object#notifyAll()
* @see java.lang.Object#wait()
* @see java.lang.Object#wait(long)
* @see java.lang.Object#wait(long, int)
* @since JDK1.0
*/
public class IllegalMonitorStateException extends RuntimeException
大致意思就是说抛出这个异常表明线程尝试等待一个对象的监视器或者去通知其他正在等待这个对象监视器的线程时,但是没有拥有这个监视器的所有权。
monitor翻译成监视器,可能大家会有些疑惑。我们可以换一个角度来解释这个问题,大家都知道Java中每个类和对象都有一个同步锁,只有获取到调用同步锁,调用wait和notify方法才行(下一篇专门讲一下Java的锁)。下面我们看几个例子就明白是怎么回事了:
实例1:
调用所属对象的wait和notify方法。
//所属对象的情况
public synchronized void notifySlef(){
this.notify();
}
或
public synchronized void waitSlef(){
this.wait();
}
//其他对象的情况
public Object lock = new Object();
public synchronized void notifySlef(){
synchronized(lock) {
lock.notify();
}
}
或
public Object lock = new Object();
public synchronized void waitSlef(){
synchronized(lock) {
lock.wait();
}
}
因为在waitSlef和notifySlef方法使用了synchronized获取了所属对象或其他对象的同步锁,所以调用wait()或者notify()方法是不会报错的。
实例2:
调用类的notify和wait方法。
public static synchronized void notifyClass() {
Test.class.notify();
}
或者
public void waitClass() {
synchronized (Test.class) {
Test.class.wait();
}
}
调用类的wait和notify方法,就要获取到类的锁。
总之,我们可以把API中所说的监视器(monitor)理解成同步锁。想要执行某个对象的notify(), notifyAll(),wait(), wait(long), wait(long, int)方法
就必须获取该对象的锁,需要使用synchronized,不然就会抛出IllegalMonitorStateException异常。