Исключение IllegalMonitorStateException при вызове wait()
Я использую многопоточность в Java для своей программы. Я успешно запустил поток, но когда я использую Thread.wait(), он выдает ошибку java.lang.IllegalMonitorStateException. Как я могу заставить поток ждать, пока он не получит уведомление?
Переведено автоматически
Ответ 1
Вы должны находиться в synchronized блоке объекта, который вы хотите ожидать, чтобы Object.wait() сработал.
Кроме того, я рекомендую обратить внимание на пакеты параллелизма вместо пакетов потоковой обработки старой школы. Они безопаснее и с ними проще работать.
Я предположил, что вы имели в виду, Object.wait() поскольку ваше исключение - это то, что происходит, когда вы пытаетесь получить доступ, не удерживая блокировку объектов.
Ответ 2
wait определено в Object, а не оно Thread. Монитор на Thread немного непредсказуем.
Хотя у всех объектов Java есть мониторы, обычно лучше иметь специальную блокировку:
privatefinalObjectlock=newObject();
Вы можете немного упростить чтение диагностики при небольших затратах памяти (около 2 КБ на процесс), используя именованный класс:
Для того, чтобы wait или notify/notifyAll объект, вам необходимо удерживать блокировку с помощью synchronized инструкции. Кроме того, вам понадобится while цикл для проверки состояния пробуждения (найдите хороший текст о потоковой обработке, чтобы объяснить, почему).
synchronized (lock) { while (!isWakeupNeeded()) { lock.wait(); } }
При переходе к многопоточности стоит научиться понимать как язык 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
Судя по вашим комментариям, похоже, что вы делаете что-то вроде этого:
Threadthread=newThread(newRunnable(){ publicvoidrun() { // do stuff }});
thread.start(); ... thread.wait();
Есть три проблемы.
Как говорили другие, obj.wait() может быть вызван только в том случае, если текущий поток содержит примитивную блокировку / мьютекс для obj. Если текущий поток не удерживает блокировку, вы получаете исключение, которое вы видите.
thread.wait() Вызов выполняет не то, что вы, похоже, ожидаете от него. В частности, thread.wait()не заставляет назначенный поток ждать. Скорее это заставляет текущий поток ждать, пока какой-нибудь другой поток не вызовет thread.notify() или thread.notifyAll().
На самом деле нет безопасного способа заставить Thread экземпляр приостановить работу, если он этого не хочет. (Ближайший к этому в Java устаревший Thread.suspend() метод, но этот метод по своей сути небезопасен, как объясняется в Javadoc . )
Если вы хотите, чтобы только что запущенный Thread процесс был приостановлен, лучший способ сделать это - создать CountdownLatch экземпляр и заставить вызов потока await() на защелке приостановить сам себя. Затем основной поток вызовет countDown() защелку, чтобы позволить приостановленному потоку продолжить.
Ортогонально предыдущим пунктам, использование Thread объекта в качестве блокировки / мьютекса может вызвать проблемы. Например, javadoc для Thread::join говорит:
В этой реализации используется цикл из this.wait вызовов, обусловленных this.isAlive. По завершении потока вызывается this.notifyAll метод. Приложениям не рекомендуется использовать экземпляры wait, notify или notifyAll on Thread.