IllegalMonitorStateException beim Aufruf von wait ()

Ich benutze Multi-Threading in Java für mein Programm. Ich habe Thread erfolgreich ausgeführt, aber wenn ich Thread.wait() , wird java.lang.IllegalMonitorStateException Thread.wait() . Wie kann ich einen Thread warten lassen, bis er benachrichtigt wird?

   

Sie müssen sich in einem synchronized Block befinden, damit Object.wait() funktionieren kann.

Außerdem empfehle ich, die Concurrency-Pakete statt der alten School-Threading-Pakete zu betrachten. Sie sind sicherer und viel einfacher zu handhaben .

Glückliche Kodierung.

BEARBEITEN

Ich nahm an, dass du Object.wait() da deine Ausnahme ist, was passiert, wenn du versuchst, Zugang zu erhalten, ohne die Objekte zu sperren.

wait ist in Object definiert und nicht in Thread . Der Monitor auf Thread ist ein wenig unberechenbar.

Obwohl alle Java-Objekte über Monitore verfügen, ist eine dedizierte Sperre im Allgemeinen besser:

 private final Object lock = new Object(); 

Mit einer benannten class können Sie die Diagnose bei geringen Speicherkosten (etwa 2 KB pro process) etwas leichter lesen:

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

Um ein Objekt zu wait oder zu notify / notifyAll , müssen Sie die Sperre mit der synchronized statement halten. Außerdem benötigen Sie eine while Schleife, um nach der Weckbedingung zu suchen (finden Sie einen guten Text im Threading, um den Grund dafür zu erklären).

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

Bemerken:

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

Es lohnt sich, sowohl die Java-Sprache als auch die java.util.concurrent.locks Sperren (und java.util.concurrent.atomic ) zu verstehen, wenn Sie mit Multithreading arbeiten. Aber verwenden Sie java.util.concurrent Datenstrukturen wann immer Sie können.

Ich weiß, dass dieser Thread fast 2 Jahre alt ist, aber ich muss ihn trotzdem schließen, da ich auch zu dieser Frage / Antwort-Sitzung mit demselben Thema gekommen bin …

Bitte lesen Sie diese Definition von illegalMonitorException immer wieder …

IllegalMonitorException wird ausgetriggers, um anzuzeigen, dass ein Thread versucht hat, auf dem Monitor eines Objekts zu warten oder andere Threads zu benachrichtigen, die auf dem Monitor eines Objekts warten, ohne den angegebenen Monitor zu besitzen.

Diese Zeile sagt immer wieder, IllegalMonitorException kommt, wenn eine der 2 Situationen auftritt ….

1> Warten Sie auf dem Monitor eines Objekts, ohne den angegebenen Monitor zu besitzen.

2> Benachrichtigen Sie andere Threads, die auf dem Monitor eines Objekts warten, ohne den angegebenen Monitor zu besitzen.

Einige könnten ihre Antworten bekommen haben … wer alle nicht, dann überprüfen Sie bitte 2 Aussagen ….

synchronisiert (Objekt)

object.wait ()

Wenn beide Objekte gleich sind, kann keine illegalMonitorException auftreten.

Lesen Sie jetzt erneut die IllegalMonitorException-Definition und Sie werden es nicht wieder vergessen …

Basierend auf deinen Kommentaren klingt es so, als ob du so etwas machst:

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

Es gibt zwei Probleme. Erstens, wie andere bereits gesagt haben, kann obj.wait() nur aufgerufen werden, wenn der aktuelle Thread den primitiven Mutex für obj . Wenn der aktuelle Thread den Mutex nicht enthält, erhalten Sie die Ausnahme, die Sie sehen.

Das zweite (wichtigere) Problem ist, dass thread.wait() nicht das tut, was Sie zu tun erwarten. Insbesondere führt thread.wait() nicht dazu, dass der nominierte Thread wartet. thread.notify() bewirkt es, dass der aktuelle Thread wartet, bis ein anderer Thread thread.notify() oder thread.notifyAll() .

Es gibt eigentlich keine sichere Möglichkeit, eine Thread-Instanz anzuhalten, wenn sie nicht möchte. (Das nächste, was Java dazu hat, ist die veraltete Methode ” Thread.suspend() “, aber diese Methode ist inhärent unsicher, wie im Javadoc erklärt.)

Wenn Sie möchten, dass der neu gestartete Thread angehalten wird, erstellen Sie am besten eine CountdownLatch-Instanz und lassen Sie den Threadaufruf await() auf dem Latch await() um ihn anzuhalten. Der Haupt-Thread würde dann countDown() auf dem Latch aufrufen, um den pausierten Thread fortzusetzen.

Da Sie keinen Code gepostet haben, arbeiten wir irgendwie im Dunkeln. Was sind die Details der Ausnahme?

Rufen Sie Thread.wait () aus dem Thread oder außerhalb auf?

Ich frage dies, weil es nach dem Javadoc für IllegalMonitorStateException ist:

Wird ausgetriggers, um anzuzeigen, dass ein Thread versucht hat, auf dem Monitor eines Objekts zu warten oder andere Threads zu benachrichtigen, die auf dem Monitor eines Objekts warten, ohne den angegebenen Monitor zu besitzen.

Um diese Antwort zu verdeutlichen, triggers dieser Aufruf zum Warten auf einen Thread auch IllegalMonitorStateException aus, obwohl er in einem synchronisierten Block aufgerufen wird:

 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) { String 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) { } } 

Thread.wait () – Aufruf sinnvoll in einem Code, der auf Thread.class -Objekt synchronisiert. Ich glaube nicht, dass du das meintest.
Du fragst

Wie kann ich einen Thread warten lassen, bis er benachrichtigt wird?

Sie können nur Ihren aktuellen Thread warten lassen. Jeder andere Thread kann nur sanft gebeten werden, zu warten, wenn er zustimmt.
Wenn Sie auf eine Bedingung warten wollen, brauchen Sie ein Lock-Objekt – Thread.class-Objekt ist eine sehr schlechte Wahl – es ist ein Singleton-AFAIK, so dass es (abgesehen von statischen Thread-Methoden) ist es gefährlich zu synchronisieren.
Details zur Synchronisation und zum Warten werden bereits von Tom Hawtin erläutert. java.lang.IllegalMonitorStateException bedeutet, dass Sie versuchen, auf ein Objekt zu warten, auf dem Sie nicht synchronisiert sind – dies ist illegal.

Ich bin mir nicht sicher, ob das jemand anderem helfen wird oder nicht, aber das war der Schlüssel, um mein Problem in der Antwort von Tom Hawtin – Tacklin zu lösen:

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

Nur die Tatsache, dass die “Sperre” als Argument in synchronized () übergeben wird und auch in “lock” verwendet wird .notifyAll ();

Sobald ich es an diesen 2 Orten gemacht habe, habe ich es funktioniert

Ich habe eine IllegalMonitorStateException erhalten, als IllegalMonitorStateException versucht habe, einen Thread in einer anderen class / einem anderen Thread zu IllegalMonitorStateException . In java 8 Sie die lock functionen der neuen Concurrency API anstelle von synchronized functionen verwenden.

Ich habe bereits Objekte für asynchronous Websocket-Transaktionen in einer WeakHashMap . Die Lösung in meinem Fall war, ein lock Objekt in einer ConcurrentHashMap für synchronous Antworten zu speichern . .wait Sie die condition.await (nicht .wait ).

Um das Multithreading zu behandeln, habe ich einen Executors.newCachedThreadPool() , um einen Thread-Pool zu erstellen.

Diejenigen, die Java Version 7.0 oder niedriger verwenden, können den Code, den ich hier benutzt habe, beziehen und es funktioniert.

 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(String[] args) { //Your Code new WaitTest().waitHere(10); //Your Code } }