Ich spiele mit der zeitgesteuerten Version von wait () in java.lang.Object herum und habe beobachtet, dass es sich in zwei verschiedenen Szenarien unterschiedlich verhält.
Szenario1: Verwenden der Standarddefinition von run () in Thread
%Vor%Fragen zu scenario1: Ich habe eine Verzögerung zwischen X und Y. Das liegt daran, dass ich wait () von main (obwohl auf t) und daher vom Callstack des mains aus anrufe Thread wird verwendet, anstatt der des zweiten Threads?
Szenario2: Subclassing Thread im laufenden Betrieb, um run () zu überschreiben, um etwas zu drucken.
%Vor%Fragen zu Szenario2: Ich verspüre überhaupt keine Verzögerung! Was hat sich geändert, nur weil ich run () außer Kraft gesetzt habe? Jetzt, jedes Mal, wenn ich das Programm starte, druckt es sofort "XI bin der zweite Thread.Y" ohne jegliche Verzögerung, was auch immer! Wo ist der Effekt von wait () weg?
Die Erklärung, wie die Thread-Endbearbeitung eine notifyAll sendet, ist relevant und korrekt, +1 von mir. Ich werde versuchen, einige Informationen darüber hinzuzufügen, warum dies relevant ist.
Wenn Sie
anrufen %Vor% im Haupt-Thread ist es der Haupt-Thread, der das Warten erledigt. t
ist der Monitor, auf den der Hauptthread wartet. Ihre Erwartung, dass dies Ihren t
-Thread zum Erliegen bringen könnte, ist falsch.
Der Monitor hier (das freigegebene Objekt, das zufällig t
ist) wird verwendet, um zwischen den verschiedenen Threads zu kommunizieren, ein Thread ruft notifyAll auf dem Monitor auf und die anderen Threads, die auf dem Monitor warten, erhalten die Benachrichtigung. Sie können sich den Monitor als einen gemeinsamen Kommunikationspunkt vorstellen.
In Ihrem ersten Beispiel wird der Thread t sofort gestartet und beendet (weil er nichts zu tun hat). Der Thread beendet und sendet seine Benachrichtigung, bevor der Hauptthread zu warten beginnt. Daher wird eine Verzögerung angezeigt, bis die Wartezeit abgelaufen ist.
Im zweiten Beispiel hat der Thread t etwas zu drucken, es gibt eine Race-Bedingung zwischen ihm und dem Haupt-Thread. Es ist ein Alleskönner, was zuerst passiert, hängt von Zeitunfällen ab. Was Sie sehen, ist, dass der Thread t
jetzt eine Zeile an die Konsole drucken muss, so dass es lange genug beschäftigt bleibt, dass es zu dem Zeitpunkt, zu dem der Haupt-Thread zu warten beginnt, noch aktiv ist Die Benachrichtigung, wenn t beendet ist, was dazu führt, dass der Haupt-Thread seine Wartezeit verkürzt.
Sie haben tatsächlich genau herausgefunden, warum Sie niemals wait
oder notify(All)
auf Thread aufrufen sollten (siehe JavaDocs für Thread). Intern verwendet Thread wait und notifyAll, um Thread.join () zu implementieren. Was im zweiten Fall passiert, ist also, dass threads instats wait, aber dann der andere thread stirbt und notifyAll () aufruft, was den Hauptthread aktiviert.
Benutze Thread.sleep
, wenn du nur auf eine verstrichene Zeit warten willst, benutze Thread.join
, wenn du wirklich auf die Beendigung des Threads warten willst. Lesen Sie auch die javadocs in Object
für die ordnungsgemäße Verwendung von wait
, notify
und notifyAll
.
javaDoc :
%Vor%wartet auf Millisekunden Millisekunden, damit dieser Thread stirbt. Eine Zeitüberschreitung von 0 bedeutet ewig zu warten. Diese Implementierung verwendet eine Schleife von this.wait Anrufe auf diese Bedingung. Wie ein Thread das beendet this.notifyAll-Methode wird aufgerufen. Es wird empfohlen, dass Anwendungen Verwenden Sie nicht warten, notify oder notifyAll auf Thread-Instanzen.
Tags und Links java multithreading wait synchronized