J'utilise le multi-threading en java pour mon programme. J'ai exécuté le fil avec succès, mais lorsque j'utilise Thread.wait()
, il lance java.lang.IllegalMonitorStateException
. Comment puis-je faire attendre un thread jusqu'à ce qu'il soit notifié?
java
multithreading
wait
prakash.panjwani
la source
la source
Réponses:
Vous devez être dans un
synchronized
bloc pourObject.wait()
pouvoir travailler.En outre, je recommande de regarder les packages de concurrence au lieu des packages de threads de la vieille école. Ils sont plus sûrs et beaucoup plus faciles à utiliser .
Bon codage.
ÉDITER
J'ai supposé que vous vouliez dire
Object.wait()
que votre exception est ce qui se passe lorsque vous essayez d'accéder sans maintenir le verrou des objets.la source
wait
est défini dansObject
, et non dans luiThread
. Le moniteur alluméThread
est un peu imprévisible.Bien que tous les objets Java aient des moniteurs, il est généralement préférable d'avoir un verrou dédié:
Vous pouvez obtenir un peu plus de facilité de lecture des diagnostics, pour un faible coût de mémoire (environ 2 Ko par processus) en utilisant une classe nommée:
Pour
wait
ounotify
/notifyAll
un objet, vous devez maintenir le verrou avec l'synchronized
instruction. De plus, vous aurez besoin d'unewhile
boucle pour vérifier la condition de réveil (trouvez un bon texte sur le filetage pour expliquer pourquoi).Prévenir:
Il vaut la peine de comprendre à la fois le langage Java et les
java.util.concurrent.locks
verrous (etjava.util.concurrent.atomic
) lorsque vous vous lancez dans le multithreading. Mais utilisezjava.util.concurrent
des structures de données chaque fois que vous le pouvez.la source
wait
, oui, vous n'y arriverez jamaisnotify
. Cependant, dans la documentation de l'API pourObject.wait
, "Le thread libère la propriété de ce moniteur". Donc, pendantwait
qu'il y est, c'est comme s'il était en dehors dessynchronized
blocs englobants (pour le même objet, il peut y avoir plusieurssynchronized
blocs sur le même objet).Je sais que ce fil a presque 2 ans mais je dois encore le fermer puisque je suis également venu à cette session de questions / réponses avec le même problème ...
Veuillez lire cette définition de illegalMonitorException encore et encore ...
IllegalMonitorException est levée pour indiquer qu'un thread a tenté d'attendre sur le moniteur d'un objet ou pour notifier d'autres threads en attente sur le moniteur d'un objet sans posséder le moniteur spécifié.
Cette ligne dit encore et encore, IllegalMonitorException survient lorsque l'une des 2 situations se produit ...
1> attendre sur le moniteur d'un objet sans posséder le moniteur spécifié.
2> notifiez les autres threads en attente sur le moniteur d'un objet sans posséder le moniteur spécifié.
Certains ont peut-être obtenu leurs réponses ... qui ne l'ont pas tous, alors veuillez vérifier 2 déclarations ...
synchronisé (objet)
object.wait ()
Si les deux objets sont identiques ... alors aucune exceptionlegalMonitorException ne peut venir.
Maintenant, lisez à nouveau la définition de IllegalMonitorException et vous ne l'oublierez plus ...
la source
D'après vos commentaires, il semble que vous faites quelque chose comme ceci:
Il y a trois problèmes.
Comme d'autres l'ont dit,
obj.wait()
ne peut être appelé que si le thread actuel détient le verrou primitif / mutex pourobj
. Si le thread actuel ne détient pas le verrou, vous obtenez l'exception que vous voyez.L'
thread.wait()
appel ne fait pas ce que vous semblez attendre de lui. Plus précisément,thread.wait()
ne fait pas attendre le thread désigné. Cela fait plutôt attendre le thread actuel jusqu'à ce qu'un autre thread appellethread.notify()
outhread.notifyAll()
.Il n'existe en fait aucun moyen sûr de forcer une
Thread
instance à se mettre en pause si elle ne le souhaite pas. (Le plus proche de Java est laThread.suspend()
méthode obsolète , mais cette méthode est intrinsèquement dangereuse, comme expliqué dans le Javadoc.)Si vous voulez que le nouveau démarré
Thread
se mette en pause, la meilleure façon de le faire est de créer uneCountdownLatch
instance et de demander au thread d'appelerawait()
le verrou pour se mettre en pause. Le thread principal appellerait alorscountDown()
le verrou pour laisser le thread mis en pause continuer.Orthogonal aux points précédents, l'utilisation d'un
Thread
objet comme verrou / mutex peut poser des problèmes. Par exemple, le javadoc pourThread::join
dit:la source
Puisque vous n'avez pas publié de code, nous travaillons en quelque sorte dans le noir. Quels sont les détails de l'exception?
Appelez-vous Thread.wait () à partir du thread ou de l'extérieur?
Je pose cette question car selon le javadoc pour IllegalMonitorStateException, c'est:
Pour clarifier cette réponse, cet appel à attendre sur un thread lève également IllegalMonitorStateException, bien qu'il ait été appelé depuis un bloc synchronisé:
la source
wait()
.worker.wait()
ligne? Ensuite, vous devriez synchroniser sur le travailleur, pas sur le verrou.Afin de traiter l'exception IllegalMonitorStateException, vous devez vérifier que toutes les invocations des méthodes wait, notify et notifyAll ont lieu uniquement lorsque le thread appelant possède le moniteur approprié . La solution la plus simple consiste à enfermer ces appels dans des blocs synchronisés. L'objet de synchronisation qui doit être invoqué dans l'instruction synchronisée est celui dont le moniteur doit être acquis.
Voici l'exemple simple pour comprendre le concept de moniteur
la source
L'appel Thread.wait () a du sens dans un code qui se synchronise sur l'objet Thread.class. Je ne pense pas que ce soit ce que tu voulais dire.
Tu demandes
Vous ne pouvez faire attendre que votre thread actuel. Tout autre fil ne peut être demandé d'attendre que doucement, s'il est d'accord.
Si vous voulez attendre une condition, vous avez besoin d'un objet de verrouillage - l'objet Thread.class est un très mauvais choix - c'est un AFAIK singleton donc la synchronisation dessus (sauf pour les méthodes statiques Thread) est dangereuse.
Les détails de la synchronisation et de l'attente sont déjà expliqués par Tom Hawtin.
java.lang.IllegalMonitorStateException
signifie que vous essayez d'attendre un objet sur lequel vous n'êtes pas synchronisé - il est illégal de le faire.la source
Je ne sais pas si cela aidera quelqu'un d'autre ou non, mais c'était l'élément clé pour résoudre mon problème dans la réponse de l'utilisateur "Tom Hawtin - tacklin" ci-dessus:
Juste le fait que le "verrou" est passé comme argument dans synchronized () et qu'il est également utilisé dans "lock" .notifyAll ();
Une fois que je l'ai fait dans ces 2 endroits, je l'ai fait fonctionner
la source
J'ai reçu un
IllegalMonitorStateException
certain temps en essayant de réveiller un thread dans / d'un autreclass
/ thread. Dans,java 8
vous pouvez utiliser leslock
fonctionnalités de la nouvelle API de concurrence au lieu desynchronized
fonctions.Je stockais déjà des objets pour
asynchronous
les transactions websocket dans un fichierWeakHashMap
. La solution dans mon cas était également de stocker unlock
objet dans unConcurrentHashMap
pour lessynchronous
réponses. Notez lecondition.await
(non.wait
).Pour gérer le multi-threading, j'ai utilisé un
Executors.newCachedThreadPool()
pour créer un pool de threads .la source
Ceux qui utilisent Java 7.0 ou une version inférieure peuvent se référer au code que j'ai utilisé ici et cela fonctionne.
la source