Ich versuche zu überprüfen, wie wait / notify in Java funktioniert.
Code:
%Vor%Ausgabe zurückgegeben
%Vor% Ich habe erwartet, dass wenn notify () ausgeführt wird, die Wartezeit vorbei sein wird & amp; System.out.println("wait over");
wird gedruckt. Aber es scheint, dass es nur gedruckt wird, wenn t
sein run()
beendet hat.
Objektmonitorsperren müssen eine einzelne Referenz derselben Sperre ausführen ...
In Ihrem Beispiel sind Sie waiting
für eine Instanz von Thread
, aber verwenden notify
von Runnable
. Stattdessen sollten Sie ein einzelnes, gemeinsames Sperrobjekt verwenden ... zum Beispiel
Ausgabe ...
%Vor% wait over
und leaving run method
können die Positionen abhängig von der Thread-Planung ändern.
Sie könnten versuchen, den Schlaf außerhalb des Blocks synchronized
zu setzen. Dadurch wird die Monitorsperre aufgehoben, sodass der Abschnitt wait
weiter ausgeführt werden kann (da er nicht gestartet werden kann, bis die Sperre aufgehoben wird)
Antwort auf aktualisierten Code:
Von Thread.sleep () Javadoc:
Bewirkt, dass der aktuell ausführende Thread in den Ruhezustand versetzt wird (Ausführung vorübergehend anhalten) angegebenen Anzahl von Millisekunden, abhängig von der Genauigkeit und Genauigkeit der System-Timer und Scheduler. Der Thread verliert keine Eigentumsrechte an Monitoren .
Wenn Sie Thread.sleep innerhalb eines synchronisierten Blocks aufrufen, können andere Threads den synchronisierten Block nicht betreten. Sie sollten niemals zeitraubende Aufgaben in einem synchronisierten Block ausführen, um dies zu vermeiden.
Beachten Sie (wie auch andere darauf hingewiesen haben), dass Sie in beiden Threads dasselbe Objekt zum Sperren / Synchronisieren verwenden müssen.
Wenn Sie möchten, dass Ihr Haupt-Thread sofort fortgesetzt wird, nachdem notify
aufgerufen wurde, müssen Sie die Sperre vorübergehend aufgeben. Andernfalls wird wait
erst aufgerufen, nachdem der sekundäre Thread den synchronized
-Block verlassen hat. Und es ist nie eine gute Idee, eine Sperre in einer lang laufenden Berechnung zu halten!
Eine Möglichkeit, wie Sie dies erreichen können, ist die Verwendung von wait(int)
für die Sperre anstelle von sleep
, weil wait
die Synchronisierungssperre vorübergehend freigibt:
Allerdings kann die Verwendung dieser Low-Level-Primitive sehr fehleranfällig sein, und ich würde davon abraten, sie zu verwenden. Stattdessen würde ich Ihnen vorschlagen, die High-Level-Primitive von Java dafür zu verwenden. Zum Beispiel können Sie CountDownLatch
verwenden, wodurch ein Thread warten kann, bis andere Threads auf Null zählen:
Hier müssen Sie nichts synchronisieren, der Riegel erledigt alles für Sie. Es gibt viele andere Grundelemente, die Sie verwenden können - Semaphore, ein Exchanger, thread-sichere Warteschlangen usw. Entdecke das java.util.concurrent
-Paket.
Vielleicht ist eine noch bessere Lösung, eine noch höhere API zu verwenden, wie Akka bietet. Dort arbeiten Sie mit Schauspielern oder Softwaretransaktionsspeicher , der leicht zusammengestellt werden kann und Ihnen die meisten Nebenläufigkeitsprobleme erspart.
Tags und Links java multithreading synchronization