调用thread.wait()时出现IllegalMonitorStateException异常求助
问题排查与解决
异常根本原因
Java中wait()、notify()、notifyAll()这三个方法的调用有强制规则:必须持有调用方法所属对象的监视器锁,否则就会直接抛出IllegalMonitorStateException。
对应你的代码逻辑:
someMethod加了synchronized修饰,实际锁的是当前SomeClass类的实例对象(即this)- 但你调用的是
thread.wait(),也就是要调用Thread类实例thread的wait方法,此时你没有持有thread对象的锁,所以直接触发异常 - 同理
restartThread方法里的thread.notify()也会触发同样的异常,因为你持有的还是SomeClass实例的锁,不是thread对象的锁。
额外注意:不建议用Thread实例作为锁对象,因为JDK内部Thread类的join等方法会用到自身的监视器锁,容易和业务逻辑产生不可预知的冲突。
其他代码问题
- 你在
someMethod的末尾递归调用自身,没有终止条件,运行一段时间后会直接出现栈溢出错误 - 测试代码里的
test.start()无法正常运行:SomeClass没有定义start方法,你需要调用内部thread对象的start方法才能启动线程 - 没有处理
wait的虚假唤醒问题:按照规范wait必须放在循环判断中,不能直接调用 TimeUnit.SECONDS.sleep(2)执行时不会释放当前持有的锁,其他线程无法进入当前类的synchronized方法
修复后的示例代码
import java.util.concurrent.TimeUnit; public class SomeClass{ // 单独定义锁对象,避免逻辑冲突 private final Object lock = new Object(); private final Thread thread = new Thread(this::someMethod); public void someMethod(){ try { // 用死循环替代递归,避免栈溢出 while (true) { synchronized (lock) { doSomething(); TimeUnit.SECONDS.sleep(2); doSomething(); // 持有锁对象的锁时调用wait,不会抛出异常 lock.wait(); } } } catch (InterruptedException e) { e.printStackTrace(); // 保留线程中断状态 Thread.currentThread().interrupt(); } } public void restartThread() { synchronized (lock) { // 持有锁对象的锁时调用notify lock.notify(); } } private void doSomething() { // 你的业务逻辑实现 } // 封装线程启动方法 public void start() { thread.start(); } public static void main(String[] args) throws InterruptedException { SomeClass test = new SomeClass(); test.start(); // 测试唤醒逻辑 TimeUnit.SECONDS.sleep(3); test.restartThread(); } }
内容的提问来源于stack exchange,提问作者MD Tate
相关产品推荐
相关产品推荐

