首先我们要了解一下Java中Wait/Notify机制。
Java中的Wait/Notify机制是一种线程间的协作方式,用于控制多个线程之间的执行顺序与互斥访问共享资源。
当一个线程调用Object.wait()方法时,它会进入阻塞状态,等待其他线程调用Object.notify()方法来唤醒它。而其他线程在调用Object.notify()方法时,会唤醒被阻塞的线程,将其从阻塞状态转移至就绪状态。
但是,在使用Wait/Notify机制时,我们需要注意以下两点:
-
Wait/Notify方法只能在同步块或同步方法内部调用(即已经获得了对象的监视器/Monitor),否则会报”IllegalMonitorStateException”异常。
-
在调用wait()方法后,当前线程会释放对象的监视器,直到它被唤醒后重新获得监视器的锁。
那么我们来看一下第一个示例:
public class WaitNotifyTest {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
obj.wait();
}
}
运行这段代码会抛出IllegalMonitorStateException异常,因为在调用obj.wait()时没有获取目标对象obj的监视器。
解决方法是将代码放在同步块或同步方法内部,并在调用wait()/notify()方法前获得监视器的锁:
public class WaitNotifyTest {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
synchronized (obj) {
obj.wait();
}
}
}
在这个示例中,我们使用了synchronized关键字来获得obj的监视器锁,并在同步块内部调用wait()方法,避免了IllegalMonitorStateException异常的抛出。
接下来我们看第二个示例:
public class WaitNotifyTest {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
obj.notify();
}
}
在这个示例中,调用obj.notify()方法不会抛出IllegalMonitorStateException异常,但是它也不能正常地唤醒其他线程。
因为唤醒其他线程需要在持有对象监视器锁的情况下进行。所以需要将代码放在同步块或同步方法内部,并在调用notify()方法前获得监视器的锁。
public class WaitNotifyTest {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
synchronized (obj) {
obj.notify();
}
}
}
这样,我们就可以正确地唤醒其他线程了。
综上所述,IllegalMonitorStateException异常的产生原因是在调用wait()/notify()方法时没有获得目标对象的监视器锁。解决方法是将代码放在同步块或同步方法内部,并在调用wait()/notify()方法前获得监视器的锁。