使用等待和通知时如何修复 IllegalMonitorStateException?

How to fix IllegalMonitorStateException when using wait and notify?

我有一个 JPanel class,它使用 "implements runnable" 启动另一个线程。这个另一个线程然后将在不同的点调用 JPanel class 中的一个方法,这样做将需要等待用户输入。我试图像这样实现它:

JPanel 中的方法class 被需要等待的其他线程调用:

public void methodToWait()
{
    while(conditionIsMet)
    {
        try
        {
            wait();
        }
        catch
        {
            e.printStackTrace();
        }
    }
}

JPanel 中的方法 class 在等待用户输入时发出通知:

public void mouseClicked(MouseEvent event)
{
    notifyAll();
}

但是,运行 应用程序在调用等待时抛出 "java.lang.IllegalMonitorStateException",为什么会这样,我该如何解决这个问题?

参见 wait, notify and notifyAll 的文档:

Thorws IllegalMonitorStateException - if the current thread is not the owner of the object's monitor.

这意味着在您获得监视器锁之前,您不能调用它们,换句话说,在您进入 synchronized block or synchronized method(check this for more 之前。


另一件重要的事情是,你应该在同一个对象上同步。

  • 当您对显式对象使用 同步块 时,您应该对该对象调用 waitnotify
  • 当您使用 同步方法 时,您是在 this 上隐式同步,因此您应该调用 this.wait()this.notify()(关键字 this 不是强制性的)。

在这种情况下,您需要创建一个 Object 作为监视器锁并在不同的 类 之间共享它。


合规示例:

synchronized (obj) {
    while (<condition does not hold>)
        obj.wait();
    ... // Perform action appropriate to condition
}

synchronized (obj) {
    ... // Prepare the condition
    obj.notifyAll();
}

不合规示例:

void waitMethod() {
    wait(); // throws IllegalMonitorStateException  
}

void notifyMethod() {
    notify(); // throws IllegalMonitorStateException  
}

不合规示例:

synchronized (obj1) {
    while (<condition does not hold>)
        obj1.wait();
    ... // Perform action appropriate to condition
}

synchronized (obj2) {
    ... // call notifyAll on obj2 will not stop the wait on obj1
    obj2.notifyAll();
}

不合规示例:

in class1
synchronized void waitMethod() {
    while(someCondition()) {
        wait(); 
    }
}

in class2
synchronized void notifyMethod() {
    notify(); // call notifyAll on class2 will not stop the wait on class1
}