Как исправить IllegalMonitorStateException при использовании wait и notify? - PullRequest
0 голосов
/ 07 мая 2018

У меня есть класс JPanel, который запускает другой поток, используя "Implements Runnable". Этот другой поток затем будет в различных точках вызывать метод в классе JPanel, который при этом должен будет ждать ввода пользователя. Я попытался реализовать это так:

Метод в классе JPanel, вызываемый другим потоком, который должен ждать:

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

Метод в классе JPanel, который уведомляет о ожидании при вводе пользователем:

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

Однако при запуске приложения оно вызывает «java.lang.IllegalMonitorStateException» при вызове wait, почему оно делает это и как мне решить проблему?

1 Ответ

0 голосов
/ 07 мая 2018

См. Документ wait, notify и notifyAll:

Thorws IllegalMonitorStateException - если текущий поток не является владелец монитора объекта.

Это означает, что вы не можете вызывать их, пока не получите блокировку монитора, другими словами, пока вы не введете синхронизированный блок или синхронизированный метод (проверьте этот для получения дополнительной информации) .


Еще одна важная вещь: вы должны синхронизироваться на одном и том же объекте.

  • Когда вы используете синхронизированный блок с объектом экспликации, вы должны вызывать wait и notify для этого объекта.
  • Когда вы используете синхронизированный метод , вы неявно синхронизируетесь с 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
}
...