Como usar esperar e notificar em Java sem IllegalMonitorStateException?
Eu tenho 2 matrizes e preciso multiplicá-las e depois imprimir os resultados de cada célula. Assim que uma célula estiver pronta, preciso imprimi-la, mas, por exemplo, preciso imprimir a célula [0] [0] antes da célula [2] [0], mesmo que o resultado de [2] [0] esteja pronto primeiro . Então, eu preciso imprimi-lo por encomenda. Então, minha idéia é fazer com que o encadeamento da impressora aguarde até multiplyThreadque ele notifique que a célula correta está pronta para ser impressa e, em seguida printerThread, imprima a célula e volte a aguardar e assim por diante.
Então, eu tenho esse segmento que faz a multiplicação:
Segmento que imprime o resultado de cada célula:
Agora isso me lança essas exceções:
a linha 49 multiplyThreadé o "notify ()". Acho que preciso usar o sincronizado de maneira diferente, mas não sei como.
Se alguém puder ajudar esse código a funcionar, eu realmente aprecio isso.
— Radiodef
Para poder chamar notify (), você precisa sincronizar no mesmo objeto.
A while(!JobCompleted);opção é geralmente uma má idéia porque ele amarra o seu CPU em 100% a verificação da mesma variável constante (ver aqui )
— Matt Lyons
while(!JobCompleted) Thread.sleep(5); não tem esse problema #
— BeniBela 25/12
Ainda tem o problema de ser algo completamente diferente. A pesquisa (verificação repetida se alguma condição é atendida, ou seja, o que você está fazendo) geralmente é menos preferida do que ser notificada se a condição for alterada (ou seja, o que eu descrevi na resposta).
@huseyintugrulbuyukisik você pode chamar waitsempre que o encadeamento atual tiver um bloqueio no objeto no qual waité chamado. Se você usa um synchronizedbloco ou um método sincronizado, é com você.
@BeniBela Mas pode-se esperar que seja mais lento, com certeza (em relação à pergunta original de Huseyin).
Ao usar os métodos waite notifyou notifyAllem Java, as seguintes coisas devem ser lembradas:
Use em notifyAllvez de notifyse você espera que mais de um encadeamento esteja esperando por um bloqueio.
Os métodos waite notifydevem ser chamados em um contexto sincronizado . Veja o link para uma explicação mais detalhada.
Sempre chame o wait()método em um loop, porque se vários threads estiverem aguardando um bloqueio e um deles tiver o bloqueio e redefinir a condição, os outros threads precisarão verificar a condição depois de acordarem para ver se precisam esperar novamente ou pode iniciar o processamento.
Use o mesmo objeto para chamada wait()e notify()método; todo objeto tem seu próprio bloqueio, portanto, chamar o wait()objeto A e o notify()objeto B não fará nenhum sentido.
— Jackob
Você precisa enfiar isso? Eu estou querendo saber o tamanho das suas matrizes e se há algum benefício em imprimir um thread enquanto o outro faz a multiplicação.
Talvez valesse a pena medir esse tempo antes de executar o trabalho de rosqueamento relativamente complexo?
Se você precisar encadear, eu criaria 'n' threads para executar a multiplicação das células (talvez 'n' seja o número de núcleos disponíveis para você) e, em seguida, use o mecanismo ExecutorService and Future para despachar várias multiplicações simultaneamente .
Dessa forma, você pode otimizar o trabalho com base no número de núcleos e usar as ferramentas de encadeamento Java de nível superior (o que deve facilitar a vida). Escreva os resultados novamente em uma matriz de recebimento e, em seguida, simplesmente imprima isso quando todas as suas tarefas futuras forem concluídas.
+1 @Greg Acho que você deve dar uma olhada no pacote java.util.concurrent, como apontado por Brian.
— ATorras 20/05/09
+1 e também verificar este livro que também vai te ensinar a maneira correta de espera uso () e notificar () jcip.net
Digamos que você tenha o aplicativo 'black box' com alguma classe nomeada BlackBoxClassque possui método doSomething();.
Além disso, você tem um observador ou ouvinte chamado onResponse(String resp)que será chamado BlackBoxClassapós um tempo desconhecido.
Digamos que não sabemos o que está acontecendo BlackBoxClasse quando devemos obter resposta, mas você não deseja continuar seu código até receber resposta ou, em outras palavras, receber uma onResponseligação. Aqui entra 'Synchronize helper':
Agora podemos implementar o que queremos:
Você só pode ligar para notificar sobre objetos onde possui o monitor deles. Então você precisa de algo como
— PaulJWilliams
notify() precisa ser sincronizado também
— takete.dk
Vou mostrar um exemplo simples da maneira correta de usar waite notifyem Java. Então, eu vou criar duas classes denominadas ThreadA e ThreadB . ThreadA chamará ThreadB.
e para a classe ThreadB:
Uso simples se você quiser Como executar threads alternativamente: -
resposta :-
Como isso funciona quando eu tenho quatro operações para executar de maneira síncrona?
— saksham Agarwal
podemos ligar para notificar para retomar a execução de objetos em espera como
retome isso chamando notificar em outro objeto da mesma classe
Para esse problema específico, por que não armazenar seus vários resultados em variáveis ​​e, quando o último de seu thread for processado, você poderá imprimir no formato que desejar. Isso é especialmente útil se você estiver usando seu histórico de trabalho em outros projetos.
— kbluue
Parece uma situação para o padrão produtor-consumidor. Se você estiver usando o java 5 ou superior, considere o uso da fila de bloqueio (java.util.concurrent.BlockingQueue) e deixe o trabalho de coordenação do encadeamento na implementação subjacente da estrutura / API. Veja o exemplo do java 5: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html ou java 7 (mesmo exemplo): http: // docs. oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
— user3044236
Você protegeu adequadamente seu bloco de código ao chamar o wait()método usando synchronized(this).
Mas você não tomou a mesma precaução ao chamar o notify()método sem usar o bloco protegido: synchronized(this)ousynchronized(someObject)
Se você consultar a página de documentação do Oracle no objeto classe, que contém wait(), notify(), notifyAll()métodos, você pode ver abaixo precaução em todos esses três métodos
Esse método deve ser chamado apenas por um encadeamento que é o proprietário do monitor desse objeto
Muitas coisas foram alteradas nos últimos 7 anos e vamos procurar outras alternativas para as synchronizedperguntas abaixo do SE: