Я использую многопоточность в Java для моей программы. Я успешно запустил поток, но когда я использую Thread.wait()
, он выбрасывает java.lang.IllegalMonitorStateException
. Как я могу заставить поток ждать, пока он не будет уведомлен?
java
multithreading
wait
prakash.panjwani
источник
источник
Ответы:
Вы должны быть в
synchronized
блоке,Object.wait()
чтобы работать.Кроме того, я рекомендую смотреть на пакеты параллелизма вместо пакетов старой школы. Они безопаснее и с ними проще работать .
Удачного кодирования.
РЕДАКТИРОВАТЬ
Я предположил, что вы имели
Object.wait()
в виду в качестве исключения то, что происходит, когда вы пытаетесь получить доступ, не удерживая блокировку объектов.источник
wait
определяется вObject
, а не этоThread
. МониторThread
немного непредсказуем.Хотя все объекты Java имеют мониторы, обычно лучше иметь выделенную блокировку:
Диагностику можно немного легче прочитать при небольших затратах памяти (около 2 КБ на процесс) с помощью именованного класса:
Чтобы
wait
илиnotify
/notifyAll
или объект, вам нужно удерживать блокировку сsynchronized
оператором. Кроме того, вам понадобитсяwhile
цикл для проверки состояния пробуждения (найдите хороший текст о потоке, чтобы объяснить, почему).Сообщать:
Стоит разобраться как в языке Java, так и в
java.util.concurrent.locks
блокировках (иjava.util.concurrent.atomic
) при работе с многопоточностью. Но используйтеjava.util.concurrent
структуры данных, когда вы можете.источник
wait
, да, вы никогда не получитеnotify
. Однако в документах API дляObject.wait
«Поток освобождает владельца этого монитора». Таким образом, вwait
то время как в нем, как будто это находится за пределами вмещающихsynchronized
блоков (для одного и того же объекта, может быть несколькоsynchronized
блоков на одном объекте).Я знаю, что этой ветке уже почти 2 года, но все еще нужно закрыть ее, так как я также пришел на этот сеанс вопросов и ответов с той же проблемой ...
Пожалуйста, прочитайте это определение нелегальнойMonitorException снова и снова ...
IllegalMonitorException генерируется, чтобы указать, что поток попытался ждать на мониторе объекта или уведомить другие потоки, ожидающие на мониторе объекта, не имея указанного монитора.
Эта строка снова и снова говорит, что IllegalMonitorException возникает, когда возникает одна из двух ситуаций ....
1> ждать на мониторе объекта, не имея указанного монитора.
2> уведомить другие потоки, ожидающие на мониторе объекта, не имея указанного монитора.
Кто-то, возможно, получил ответы ... а кто нет, тогда, пожалуйста, проверьте 2 утверждения ...
синхронизированный (объект)
Object.wait ()
Если оба объекта одинаковы ... тогда не может появиться нелегальное исключение.
Теперь снова прочитайте определение IllegalMonitorException, и вы не забудете его снова ...
источник
На основании ваших комментариев кажется, что вы делаете что-то вроде этого:
Есть три проблемы.
Как уже говорили другие,
obj.wait()
может быть вызван , только если текущий поток содержит примитив блокировки / мьютекс дляobj
. Если текущий поток не удерживает блокировку, вы получаете исключение, которое вы видите.thread.wait()
Вызов не делать то , что вы , кажется, ожидая , что это сделать. В частности,thread.wait()
не заставляет назначенный поток ждать. Скорее это заставляет текущий поток ждать, пока некоторые другие потоки не вызовутthread.notify()
илиthread.notifyAll()
.На самом деле не существует безопасного способа заставить
Thread
экземпляр сделать паузу, если он этого не хочет. (Ближайшее, что есть в Java, - это устаревшийThread.suspend()
метод, но этот метод небезопасен, как объясняется в Javadoc.)Если вы хотите, чтобы вновь начавшаяся
Thread
пауза, лучший способ сделать это - создатьCountdownLatch
экземпляр и сделать так, чтобы поток вызвалawait()
защелку, чтобы сделать паузу самостоятельно. Затем основной поток вызываетcountDown()
защелку, чтобы позволить приостановленной нити продолжить.Ортогонально предыдущим точкам, использование
Thread
объекта в качестве блокировки / мьютекса может вызвать проблемы. Например, Javadoc дляThread::join
говорит:источник
Поскольку вы не опубликовали код, мы вроде как работаем в темноте. Каковы детали исключения?
Вы вызываете Thread.wait () из потока или вне его?
Я спрашиваю об этом, потому что в соответствии с Javadoc для IllegalMonitorStateException, это:
Чтобы прояснить этот ответ, этот вызов ожидания в потоке также вызывает исключение IllegalMonitorStateException, несмотря на то, что он вызывается из синхронизированного блока:
источник
wait()
.worker.wait()
линии? Тогда вы должны синхронизироваться на рабочем, а не на блокировке.Чтобы иметь дело с IllegalMonitorStateException, вы должны убедиться, что все вызовы методов wait, notify и notifyAll происходят только тогда, когда вызывающий поток владеет соответствующим монитором . Самое простое решение - заключить эти вызовы в синхронизированные блоки. Объект синхронизации, который должен вызываться в операторе синхронизации, - это тот, чей монитор должен быть получен.
Вот простой пример, чтобы понять концепцию монитора
источник
Вызов Thread.wait () имеет смысл внутри кода, который синхронизируется с объектом Thread.class. Я не думаю, что это то, что вы имели в виду.
Ты спрашиваешь
Вы можете подождать только вашу текущую тему. Любую другую ветку можно только осторожно попросить подождать, если она согласится.
Если вы хотите дождаться какого-то условия, вам нужен объект блокировки - объект Thread.class - очень плохой выбор - это одноэлементный AFAIK, поэтому синхронизация с ним (за исключением статических методов Thread) опасна.
Подробности синхронизации и ожидания уже объясняются Томом Хоутином.
java.lang.IllegalMonitorStateException
означает, что вы пытаетесь дождаться объекта, с которым вы не синхронизированы - это незаконно.источник
Не уверен, поможет ли это кому-то еще или нет, но это было ключевым моментом, чтобы исправить мою проблему в ответе пользователя "Tom Hawtin - tacklin" выше:
Просто тот факт, что «lock» передается в качестве аргумента в synchronized (), и он также используется в «lock» .notifyAll ();
Как только я сделал это в тех 2 местах, я получил это работает
источник
Я получил некоторое
IllegalMonitorStateException
время, пытаясь разбудить поток в / из другогоclass
/ потока. Вjava 8
вы можете использоватьlock
функции нового параллелизма API вместо изsynchronized
функций.Я уже хранил объекты для
asynchronous
транзакций websocket вWeakHashMap
. Решение в моем случае состояло в том, чтобы также сохранитьlock
объект вConcurrentHashMap
дляsynchronous
ответов. Обратите внимание наcondition.await
(не.wait
).Для обработки многопоточности я использовал
Executors.newCachedThreadPool()
для создания пула потоков .источник
Те, кто использует версию Java 7.0 или ниже, могут ссылаться на код, который я использовал здесь, и он работает.
источник