Ich verwende Multithreading in Java für mein Programm. Ich habe den Thread erfolgreich ausgeführt, aber wenn ich ihn verwende Thread.wait()
, wird er ausgelöst java.lang.IllegalMonitorStateException
. Wie kann ich einen Thread warten lassen, bis er benachrichtigt wird?
java
multithreading
wait
prakash.panjwani
quelle
quelle
Antworten:
Sie müssen sich in einem
synchronized
Block befinden, umObject.wait()
arbeiten zu können.Außerdem empfehle ich, die Parallelitätspakete anstelle der Threading-Pakete der alten Schule zu betrachten. Sie sind sicherer und viel einfacher zu bearbeiten .
Viel Spaß beim Codieren.
BEARBEITEN
Ich nahm an, Sie meinten
Object.wait()
als Ihre Ausnahme, was passiert, wenn Sie versuchen, Zugriff zu erhalten, ohne die Objektsperre zu halten.quelle
wait
ist definiert inObject
und nicht esThread
. Der eingeschaltete MonitorThread
ist etwas unvorhersehbar.Obwohl alle Java-Objekte über Monitore verfügen, ist es im Allgemeinen besser, eine dedizierte Sperre zu haben:
Durch die Verwendung einer benannten Klasse können Sie die Diagnose bei geringen Speicherkosten (ca. 2 KB pro Prozess) etwas einfacher lesen:
Um zu
wait
odernotify
/notifyAll
ein Objekt zu gelangen, müssen Sie die Sperre mit dersynchronized
Anweisung halten. Außerdem benötigen Sie einewhile
Schleife, um den Weckzustand zu überprüfen (finden Sie einen guten Text zum Threading, um zu erklären, warum).Bemerken:
Es lohnt sich, sowohl die Java-Sprache als auch die
java.util.concurrent.locks
Sperren (undjava.util.concurrent.atomic
) zu verstehen, wenn Sie sich mit Multithreading beschäftigen. Verwenden Sie jedochjava.util.concurrent
Datenstrukturen, wann immer Sie können.quelle
wait
, ja, du würdest nie dazu kommennotify
. In den API-Dokumenten fürObject.wait
"Der Thread gibt jedoch den Besitz dieses Monitors frei". Währendwait
es so ist, als ob es sich außerhalb der umschließendensynchronized
Blöcke befindet (für dasselbe Objekt können sich mehreresynchronized
Blöcke auf demselben Objekt befinden).Ich weiß, dass dieser Thread fast 2 Jahre alt ist, muss ihn aber noch schließen, da ich auch mit demselben Problem zu dieser Q / A-Sitzung gekommen bin ...
Bitte lesen Sie diese Definition von illegalMonitorException immer wieder ...
IllegalMonitorException wird ausgelöst, 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, dass IllegalMonitorException auftritt, wenn eine der beiden Situationen eintritt ....
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 haben vielleicht ihre Antworten bekommen ... wer alles nicht, dann überprüfen Sie bitte 2 Aussagen ...
synchronisiert (Objekt)
object.wait ()
Wenn beide Objekte gleich sind ... kann keine illegalMonitorException auftreten.
Lesen Sie jetzt noch einmal die IllegalMonitorException-Definition und Sie werden sie nicht wieder vergessen ...
quelle
Aufgrund Ihrer Kommentare klingt es so, als würden Sie so etwas tun:
Es gibt drei Probleme.
Wie andere gesagt haben,
obj.wait()
kann nur aufgerufen werden, wenn der aktuelle Thread die primitive Sperre / Mutex für enthältobj
. Wenn der aktuelle Thread die Sperre nicht hält, wird die angezeigte Ausnahme angezeigt.Der
thread.wait()
Anruf macht nicht das, was Sie zu erwarten scheinen. Insbesondere führtthread.wait()
dies nicht dazu, dass der nominierte Thread wartet. Vielmehr wartet der aktuelle Thread , bis ein anderer Threadthread.notify()
oder aufruftthread.notifyAll()
.Es gibt eigentlich keine sichere Möglichkeit, eine
Thread
Instanz zum Anhalten zu zwingen , wenn sie dies nicht möchte. (Das, was Java am nächsten kommt, ist die veralteteThread.suspend()
Methode, aber diese Methode ist von Natur aus unsicher, wie im Javadoc erläutert.)Wenn Sie möchten, dass das neu gestartete
Thread
Programm angehalten wird, erstellen Sie am besten eineCountdownLatch
Instanz und lassen den Thread-Aufrufawait()
des Latches anhalten, um sich selbst anzuhalten. Der Haupt-Thread würde danncountDown()
die Verriegelung aufrufen , um den angehaltenen Thread fortzusetzen.Orthogonal zu den vorherigen Punkten kann die Verwendung eines
Thread
Objekts als Sperre / Mutex Probleme verursachen. Zum BeispielThread::join
sagt der Javadoc für :quelle
Da Sie keinen Code gepostet haben, arbeiten wir im Dunkeln. Was sind die Details der Ausnahme?
Rufen Sie Thread.wait () innerhalb oder außerhalb des Threads auf?
Ich frage dies, weil es laut Javadoc für IllegalMonitorStateException ist:
Um diese Antwort zu verdeutlichen, löst dieser Aufruf zum Warten auf einen Thread auch IllegalMonitorStateException aus, obwohl er aus einem synchronisierten Block heraus aufgerufen wird:
quelle
wait()
.worker.wait()
Linie? Dann sollten Sie auf dem Worker synchronisieren, nicht auf dem Schloss.Um mit der IllegalMonitorStateException umgehen zu können, müssen Sie überprüfen, ob alle Aufrufe der Methoden wait, notify und notifyAll nur stattfinden, wenn der aufrufende Thread den entsprechenden Monitor besitzt . Die einfachste Lösung besteht darin, diese Aufrufe in synchronisierte Blöcke einzuschließen. Das Synchronisationsobjekt, das in der synchronisierten Anweisung aufgerufen werden soll, ist dasjenige, dessen Monitor erfasst werden muss.
Hier ist das einfache Beispiel, um das Konzept des Monitors zu verstehen
quelle
Der Aufruf von Thread.wait () ist in einem Code sinnvoll, der mit dem Thread.class-Objekt synchronisiert wird. Ich glaube nicht, dass du das gemeint hast.
Du fragst
Sie können nur Ihren aktuellen Thread warten lassen. Jeder andere Thread kann nur sanft zum Warten aufgefordert werden, wenn er zustimmt.
Wenn Sie auf eine Bedingung warten möchten, benötigen Sie ein Sperrobjekt - Thread.class-Objekt ist eine sehr schlechte Wahl - es ist ein Singleton-AFAIK, daher ist die Synchronisierung darauf (mit Ausnahme der statischen Thread-Methoden) gefährlich.
Details zur Synchronisation und zum Warten werden bereits von Tom Hawtin erklärt.
java.lang.IllegalMonitorStateException
bedeutet, dass Sie versuchen, auf ein Objekt zu warten, auf dem Sie nicht synchronisiert sind - dies ist illegal.quelle
Ich bin mir nicht sicher, ob dies jemand anderem helfen wird oder nicht, aber dies war der Schlüssel zur Behebung meines Problems in der obigen Antwort von Benutzer "Tom Hawtin - Tacklin":
Nur die Tatsache, dass die "Sperre" als Argument in synchronized () übergeben wird und auch in "lock" .notifyAll () verwendet wird;
Sobald ich es an diesen 2 Orten geschafft habe, habe ich es zum Laufen gebracht
quelle
Ich habe eine
IllegalMonitorStateException
Weile versucht, einen Thread in / von einem anderenclass
/ Thread aufzuwecken . In könnenjava 8
Sie dielock
Funktionen der neuen Concurrency-API anstelle vonsynchronized
Funktionen verwenden.Ich habe bereits Objekte für
asynchronous
Websocket-Transaktionen in einem gespeichertWeakHashMap
. Die Lösung in meinem Fall bestand darin , einlock
Objekt auch in einemConcurrentHashMap
fürsynchronous
Antworten zu speichern . Beachten Sie diecondition.await
(nicht.wait
).Um das Multithreading zu handhaben, habe ich a verwendet
Executors.newCachedThreadPool()
, um einen Thread-Pool zu erstellen .quelle
Diejenigen, die Java 7.0 oder eine niedrigere Version verwenden, können auf den Code verweisen, den ich hier verwendet habe, und er funktioniert.
quelle