Estou usando o multi-threading em java para o meu programa. Eu executei o thread com êxito, mas quando estou usando Thread.wait()
, ele está sendo lançado java.lang.IllegalMonitorStateException
. Como posso fazer com que um thread aguarde até ser notificado?
java
multithreading
wait
prakash.panjwani
fonte
fonte
Respostas:
Você precisa estar em um
synchronized
bloco paraObject.wait()
poder trabalhar.Além disso, recomendo examinar os pacotes de simultaneidade em vez dos pacotes de threading da velha escola. Eles são mais seguros e fáceis de trabalhar .
Feliz codificação.
EDITAR
Supus que você quis dizer
Object.wait()
que sua exceção é o que acontece quando você tenta obter acesso sem manter o bloqueio de objetos.fonte
wait
é definido emObject
, e não eleThread
. O monitor ligadoThread
é um pouco imprevisível.Embora todos os objetos Java tenham monitores, geralmente é melhor ter um bloqueio dedicado:
Você pode obter um pouco mais fácil de ler os diagnósticos, com um pequeno custo de memória (cerca de 2 K por processo) usando uma classe nomeada:
Para /
wait
ou um objeto, você precisa estar segurando a trava com a instrução Além disso, você precisará de um loop para verificar a condição de ativação (encontre um bom texto sobre o encadeamento para explicar o porquê).notify
notifyAll
synchronized
while
Para notificar:
Vale a pena entender a linguagem Java e os
java.util.concurrent.locks
bloqueios (ejava.util.concurrent.atomic
) ao entrar no multithreading. Mas usejava.util.concurrent
estruturas de dados sempre que puder.fonte
wait
, sim, você nunca chegaria a issonotify
. No entanto, nos documentos da API paraObject.wait
"O encadeamento libera a propriedade deste monitor". Portanto, enquantowait
está como se estivesse fora dossynchronized
blocos anexos (para o mesmo objeto, pode haver váriossynchronized
blocos no mesmo objeto).Eu sei que este tópico tem quase 2 anos, mas ainda preciso encerrar isso, pois também participei dessa sessão de perguntas e respostas com o mesmo problema ...
Por favor, leia esta definição de ilegalMonitorException repetidamente ...
IllegalMonitorException é acionada para indicar que um encadeamento tentou aguardar no monitor de um objeto ou para notificar outros encadeamentos que aguardam no monitor de um objeto sem possuir o monitor especificado.
Essa linha diz repetidamente que IllegalMonitorException ocorre quando ocorre uma das 2 situações ....
1> aguarde no monitor de um objeto sem possuir o monitor especificado.
2> notificar outros threads que aguardam no monitor de um objeto sem possuir o monitor especificado.
Alguns podem ter suas respostas ... quem não sabe, por favor, verifique duas instruções ....
sincronizado (objeto)
object.wait ()
Se ambos os objetos forem iguais ... então nenhuma ilegalMonitorException poderá aparecer.
Agora leia novamente a definição IllegalMonitorException e você não a esquecerá novamente ...
fonte
Com base nos seus comentários, parece que você está fazendo algo parecido com isto:
Existem três problemas.
Como outros já disseram,
obj.wait()
só pode ser chamado se o encadeamento atual contiver o bloqueio / mutex primitivo paraobj
. Se o encadeamento atual não reter o bloqueio, você obtém a exceção que está vendo.A
thread.wait()
chamada não faz o que você espera. Especificamente,thread.wait()
não faz com que o segmento indicado aguarde. Em vez disso, faz com que o encadeamento atual aguarde até que outro encadeamento chamethread.notify()
outhread.notifyAll()
.Na verdade, não há maneira segura de forçar uma
Thread
instância a pausar, se ela não quiser. (O Java mais próximo disso é oThread.suspend()
método obsoleto , mas esse método é inerentemente inseguro, conforme explicado no Javadoc.)Se você deseja que o recém-iniciado faça
Thread
uma pausa, a melhor maneira de fazer isso é criar umaCountdownLatch
instância e fazer com que a chamada de encadeamentoawait()
na trava seja pausada. O encadeamento principal chamariacountDown()
a trava para permitir que o encadeamento em pausa continuasse.Ortogonal aos pontos anteriores, o uso de um
Thread
objeto como bloqueio / mutex pode causar problemas. Por exemplo, o javadoc paraThread::join
diz:fonte
Como você não publicou o código, estamos trabalhando no escuro. Quais são os detalhes da exceção?
Você está chamando Thread.wait () de dentro ou fora dele?
Eu pergunto isso porque, de acordo com o javadoc para IllegalMonitorStateException, é:
Para esclarecer esta resposta, essa chamada para aguardar um thread também lança IllegalMonitorStateException, apesar de ser chamada de dentro de um bloco sincronizado:
fonte
wait()
.worker.wait()
linha? Então você deve estar sincronizando no trabalhador, não no cadeado.Para lidar com o IllegalMonitorStateException, você deve verificar se todas as chamadas dos métodos wait, notify e notifyAll estão ocorrendo apenas quando o encadeamento de chamada possui o monitor apropriado . A solução mais simples é colocar essas chamadas dentro de blocos sincronizados. O objeto de sincronização que deve ser chamado na instrução sincronizada é aquele cujo monitor deve ser adquirido.
Aqui está o exemplo simples para entender o conceito de monitor
fonte
A chamada Thread.wait () faz sentido dentro de um código que sincroniza no objeto Thread.class. Eu não acho que é o que você quis dizer.
Você pergunta
Você pode fazer apenas seu thread atual aguardar. Qualquer outro segmento pode ser gentilmente solicitado a aguardar, se concordar.
Se você quiser esperar por alguma condição, precisará de um objeto de bloqueio - o objeto Thread.class é uma péssima escolha - é um AFAIK único, portanto a sincronização nele (exceto os métodos estáticos do Thread) é perigosa.
Detalhes para sincronização e espera já são explicados por Tom Hawtin.
java.lang.IllegalMonitorStateException
significa que você está tentando esperar um objeto no qual não está sincronizado - é ilegal fazê-lo.fonte
Não tenho certeza se isso ajudará ou não alguém, mas esta foi a parte principal para corrigir meu problema na resposta do usuário "Tom Hawtin-tacklin" acima:
Apenas o fato de o "bloqueio" ser passado como argumento em synchronized () e também ser usado em "bloqueio" .notifyAll ();
Uma vez que eu fiz nesses 2 lugares eu consegui trabalhar
fonte
Recebi um
IllegalMonitorStateException
tempo tentando ativar um thread em / de umclass
/ thread diferente . Emjava 8
você pode usar oslock
recursos da nova API de simultaneidade em vez desynchronized
funções.Eu já estava armazenando objetos para
asynchronous
transações de websocket em um arquivoWeakHashMap
. A solução no meu caso foi também armazenar umlock
objeto em umConcurrentHashMap
parasynchronous
respostas. Observe ocondition.await
(não.wait
).Para lidar com o multi threading, usei a
Executors.newCachedThreadPool()
para criar um pool de threads .fonte
Aqueles que estão usando o Java 7.0 ou versão inferior podem consultar o código que eu usei aqui e ele funciona.
fonte