如何在使用wait和notify时修复IllegalMonitorStateException?

时间:2018-05-07 13:39:37

标签: java multithreading wait notify

我有一个JPanel类,它使用&#34启动另一个线程;实现runnable"。然后,这个其他线程将在各个点调用JPanel类中的一个方法,然后这样做将需要等待用户输入。我试图像这样实现它:

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

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

JPanel类中通知用户输入等待的方法:

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

然而,在运行应用程序时,它会抛出一个" java.lang.IllegalMonitorStateException"在调用等待时,为什么要这样做,我该如何解决这个问题呢?

1 个答案:

答案 0 :(得分:5)

请参阅waitnotifynotifyAll的文档:

  

Thorws IllegalMonitorStateException - 如果当前线程不是   对象监视器的所有者。

这意味着在获得监视器锁定之前,您无法调用它们,换句话说,直到您输入synchronized块或同步方法(检查this以获取更多信息)。

另一个重要的事情是,您应该在同一个对象上进行同步。

  • 当您将 synchronized block 与explict对象一起使用时,您应该在此对象上调用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
}