Вопрос-ответ

IllegalMonitorStateException on wait() call

Исключение IllegalMonitorStateException при вызове wait()

Я использую многопоточность в Java для своей программы. Я успешно запустил поток, но когда я использую Thread.wait(), он выдает ошибку java.lang.IllegalMonitorStateException. Как я могу заставить поток ждать, пока он не получит уведомление?

Переведено автоматически
Ответ 1

Вы должны находиться в synchronized блоке объекта, который вы хотите ожидать, чтобы Object.wait() сработал.

Кроме того, я рекомендую обратить внимание на пакеты параллелизма вместо пакетов потоковой обработки старой школы. Они безопаснее и с ними проще работать.

Я предположил, что вы имели в виду, Object.wait() поскольку ваше исключение - это то, что происходит, когда вы пытаетесь получить доступ, не удерживая блокировку объектов.

Ответ 2

wait определено в Object, а не оно Thread. Монитор на Thread немного непредсказуем.

Хотя у всех объектов Java есть мониторы, обычно лучше иметь специальную блокировку:

private final Object lock = new Object();

Вы можете немного упростить чтение диагностики при небольших затратах памяти (около 2 КБ на процесс), используя именованный класс:

private static final class Lock { }
private final Object lock = new Lock();

Для того, чтобы wait или notify/notifyAll объект, вам необходимо удерживать блокировку с помощью synchronized инструкции. Кроме того, вам понадобится while цикл для проверки состояния пробуждения (найдите хороший текст о потоковой обработке, чтобы объяснить, почему).

synchronized (lock) {
while (!isWakeupNeeded()) {
lock.wait();
}
}

Для уведомления:

synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}

При переходе к многопоточности стоит научиться понимать как язык Java, так и java.util.concurrent.locks блокировки (и java.util.concurrent.atomic). Но используйте java.util.concurrent структуры данных, когда можете.

Ответ 3

Я знаю, что этому потоку почти 2 года, но все равно нужно закрыть его, так как я также пришел на этот сеанс вопросов и ответов с той же проблемой...

Пожалуйста, прочтите это определение IllegalMonitorException снова и снова...

Исключение IllegalMonitorException выдается, чтобы указать, что поток попытался выполнить ожидание на мониторе объекта, или уведомить другие потоки, ожидающие на мониторе объекта, не владея указанным монитором.

В этой строке снова и снова говорится, что исключение IllegalMonitorException возникает при возникновении одной из двух ситуаций....

1> ждать на мониторе объекта, не владея указанным монитором.

2> уведомлять другие потоки, ожидающие на мониторе объекта, не владея указанным монитором.

Некоторые, возможно, получили ответы на свои вопросы... кто не все, тогда, пожалуйста, проверьте 2 инструкции....

синхронизировано (объект)

object.wait()

Если оба объекта одинаковы ... то исключение IllegalMonitorException не может возникнуть.

Теперь еще раз прочтите определение IllegalMonitorException, и вы больше его не забудете...

Ответ 4

Судя по вашим комментариям, похоже, что вы делаете что-то вроде этого:

Thread thread = new Thread(new Runnable(){
public void run() { // do stuff }});

thread.start();
...
thread.wait();

Есть три проблемы.


  1. Как говорили другие, obj.wait() может быть вызван только в том случае, если текущий поток содержит примитивную блокировку / мьютекс для obj. Если текущий поток не удерживает блокировку, вы получаете исключение, которое вы видите.


  2. thread.wait() Вызов выполняет не то, что вы, похоже, ожидаете от него. В частности, thread.wait() не заставляет назначенный поток ждать. Скорее это заставляет текущий поток ждать, пока какой-нибудь другой поток не вызовет thread.notify() или thread.notifyAll().


    На самом деле нет безопасного способа заставить Thread экземпляр приостановить работу, если он этого не хочет. (Ближайший к этому в Java устаревший Thread.suspend() метод, но этот метод по своей сути небезопасен, как объясняется в Javadoc . )


    Если вы хотите, чтобы только что запущенный Thread процесс был приостановлен, лучший способ сделать это - создать CountdownLatch экземпляр и заставить вызов потока await() на защелке приостановить сам себя. Затем основной поток вызовет countDown() защелку, чтобы позволить приостановленному потоку продолжить.


  3. Ортогонально предыдущим пунктам, использование Thread объекта в качестве блокировки / мьютекса может вызвать проблемы. Например, javadoc для Thread::join говорит:



    В этой реализации используется цикл из this.wait вызовов, обусловленных this.isAlive. По завершении потока вызывается this.notifyAll метод. Приложениям не рекомендуется использовать экземпляры wait, notify или notifyAll on Thread.



java multithreading