IllegalMonitorStateException à l’appel wait ()

J’utilise le multi-threading en Java pour mon programme. J’ai exécuté le thread avec succès, mais lorsque j’utilise Thread.wait() , il lance une java.lang.IllegalMonitorStateException . Comment puis-je faire un thread en attente jusqu’à ce qu’il soit notifié?

Vous devez être dans un bloc synchronized pour que Object.wait() fonctionne.

En outre, je recommande de regarder les paquets de concurrence au lieu des paquets de threading old school. Ils sont plus sûrs et plus faciles à travailler .

Heureux codage

MODIFIER

J’ai supposé que vous Object.wait() dire Object.wait() car votre exception est ce qui se produit lorsque vous essayez d’accéder sans verrouiller les objects.

wait est défini dans Object , et non Thread . Le moniteur sur le Thread est un peu imprévisible.

Bien que tous les objects Java aient des moniteurs, il est généralement préférable d’avoir un verrou dédié:

 private final Object lock = new Object(); 

Vous pouvez être légèrement plus facile à lire les diagnostics, à un faible coût en mémoire (environ 2 Ko par processus) en utilisant une classe nommée:

 private static final class Lock { } private final Object lock = new Lock(); 

Pour wait ou notify / notifyAll un object, vous devez conserver le verrou avec l’instruction synchronized . En outre, vous aurez besoin d’une boucle while pour vérifier la condition de réveil (trouvez un bon texte sur le threading pour expliquer pourquoi).

 synchronized (lock) { while (!isWakeupNeeded()) { lock.wait(); } } 

Prévenir:

 synchronized (lock) { makeWakeupNeeded(); lock.notifyAll(); } 

Cela vaut la peine de comprendre à la fois le langage Java et les verrous java.util.concurrent.locks (et java.util.concurrent.atomic ) lors du passage au multithreading. Mais utilisez les structures de données java.util.concurrent quand vous le pouvez.

Je sais que ce sujet a presque 2 ans mais que je dois encore le fermer car je suis également venu à cette session de questions / réponses avec le même problème …

S’il vous plaît lire cette définition de illegalMonitorException encore et encore …

IllegalMonitorException est renvoyé pour indiquer qu’un thread a tenté d’attendre sur le moniteur d’un object ou pour notifier d’autres threads en attente sur le moniteur d’un object sans posséder le moniteur spécifié.

Cette ligne répète encore et encore, IllegalMonitorException se produit lorsqu’une des deux situations se produit ….

1> attendez sur le moniteur d’un object sans posséder le moniteur spécifié.

2> notifie les autres threads en attente sur le moniteur d’un object sans posséder le moniteur spécifié.

Certains ont peut-être eu leurs réponses … qui tous ne le font pas, alors s’il vous plaît vérifier 2 déclarations ….

synchronisé (object)

object.wait ()

Si les deux objects sont identiques … alors aucune exception illégale Monitor peut arriver.

Maintenant, lisez à nouveau la définition d’IllegalMonitorException et vous ne l’oublierez plus …

Sur la base de vos commentaires, il semble que vous faites quelque chose comme ceci:

 Thread thread = new Thread(new Runnable(){ public void run() { // do stuff }}); thread.start(); ... thread.wait(); 

Il y a deux problèmes. Tout d’abord, comme d’autres l’ont dit, obj.wait() ne peut être appelé que si le thread en cours contient le mutex primitif pour obj . Si le thread en cours ne contient pas le mutex, vous obtenez l’exception que vous voyez.

Le deuxième problème (plus important) est que thread.wait() ne fait pas ce que vous attendez de lui. En particulier, thread.wait() n’attend pas le thread désigné. Au contraire, le thread actuel attend que d’autres threads appellent thread.notify() ou thread.notifyAll() .

Il n’y a en fait aucun moyen sûr de forcer une instance Thread à faire une pause si elle ne le souhaite pas. (La méthode la plus proche de Java est la Thread.suspend() obsolète Thread.suspend() , mais cette méthode est insortingnsèquement peu sûre, comme cela est expliqué dans le Javadoc.)

Si vous souhaitez que le thread nouvellement démarré se mette en pause, la meilleure façon de le faire est de créer une instance CountdownLatch et que l’appel de threads await() sur le verrou pour qu’il se mette en pause. Le thread principal appelle alors countDown() sur le verrou pour laisser le thread en pause continuer.

Comme vous n’avez pas posté de code, nous travaillons en quelque sorte dans le noir. Quels sont les détails de l’exception?

Appelez-vous Thread.wait () depuis le thread, ou en dehors?

Je demande ceci parce que selon le javadoc pour IllegalMonitorStateException, c’est:

Émis pour indiquer qu’un thread a tenté d’attendre sur le moniteur d’un object ou pour notifier d’autres threads en attente sur le moniteur d’un object sans posséder le moniteur spécifié.

Pour clarifier cette réponse, cet appel à attendre sur un thread lance également une exception IllegalMonitorStateException, bien qu’elle soit appelée depuis un bloc synchronisé:

 private static final class Lock { } private final Object lock = new Lock(); @Test public void testRun() { ThreadWorker worker = new ThreadWorker(); System.out.println ("Starting worker"); worker.start(); System.out.println ("Worker started - telling it to wait"); try { synchronized (lock) { worker.wait(); } } catch (InterruptedException e1) { Ssortingng msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]"; System.out.println (msg); e1.printStackTrace(); System.out.flush(); } System.out.println ("Worker done waiting, we're now waiting for it by joining"); try { worker.join(); } catch (InterruptedException ex) { } } 

L’appel Thread.wait () prend tout son sens dans un code qui se synchronise sur l’object Thread.class. Je ne pense pas que ce soit ce que tu voulais dire.
Tu demandes

Comment puis-je faire un thread en attente jusqu’à ce qu’il soit notifié?

Vous ne pouvez attendre que votre thread actuel. Tout autre fil ne peut être que doucement demandé d’attendre, s’il est d’accord.
Si vous voulez attendre une condition, vous avez besoin d’un object de locking – l’object Thread.class est un très mauvais choix – c’est un singleton AFAIK, donc la synchronisation (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 object sur lequel vous n’êtes pas synchronisé – il est illégal de le faire.

Je ne suis pas sûr que cela aidera quelqu’un d’autre ou pas, mais c’était la clé pour résoudre mon problème avec la réponse ci-dessus de l’utilisateur “Tom Hawtin – tacklin”:

 synchronized (lock) { makeWakeupNeeded(); lock.notifyAll(); } 

Juste le fait que le “verrou” est passé en argument dans synchronized () et qu’il est aussi utilisé dans “lock” .notifyAll ();

Une fois que je l’ai fait dans ces 2 endroits, je l’ai fait fonctionner

J’ai reçu une IllegalMonitorStateException en essayant de réveiller un thread dans / d’une class / thread différent. Dans java 8 vous pouvez utiliser les fonctions de lock de la nouvelle API de simultanéité au lieu des fonctions synchronized .

Je WeakHashMap déjà des objects pour asynchronous transactions websocket asynchronous dans un WeakHashMap . La solution dans mon cas consistait également à stocker un object de lock dans un ConcurrentHashMap pour synchronous réponses synchronous . Notez la condition.await (pas .wait ).

Pour gérer le multi-thread, j’ai utilisé un Executors.newCachedThreadPool() pour créer un pool de threads .

Ceux qui utilisent Java 7.0 ou une version inférieure peuvent consulter le code que j’ai utilisé ici et cela fonctionne.

 public class WaitTest { private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); public void waitHere(long waitTime) { System.out.println("wait started..."); lock.lock(); try { condition.await(waitTime, TimeUnit.SECONDS); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } lock.unlock(); System.out.println("wait ends here..."); } public static void main(Ssortingng[] args) { //Your Code new WaitTest().waitHere(10); //Your Code } }