Wie lange wartet ein Thread nach der Ausführung von wait (), wenn er nicht von anderen Threads benachrichtigt wird?
Im folgenden Beispiel sollte der Hauptthread ewig warten, da er nicht vom untergeordneten Thread benachrichtigt wird. Der Haupt-Thread wird jedoch ausgeführt und die Ausgabe des folgenden Beispiels lautet:
c
l
total: 19900
Warum wird der Haupt-Thread ausgeführt?
public class ThreadX extends Thread {
static int total = 0;
public void run() {
synchronized (this) {
for (int i = 0; i < 200; i++) {
total = total + i;
}
System.out.println("c");
}
}
public static void main(String[] args) throws InterruptedException {
ThreadX t = new ThreadX();
t.start();
synchronized (t) {
t.wait();
System.out.println("l");
}
System.out.println("total: " + total);
}
}
Antworten
Antwort auf den Fragetext
Check out Thread#join(long):
[...] Wenn ein Thread beendet wird, wird die
this.notifyAll
Methode aufgerufen. [...]
Beachten Sie, Thread#join()
dass diese Funktion mit aufgerufen wird 0
, was für immer bedeutet.
[...] Eine Zeitüberschreitung von 0 bedeutet, für immer zu warten.
In Ihrem Fall wird hier also t
nur aufgerufen, notifyAll
wenn es beendet wird, wodurch der Haupt-Thread benachrichtigt wird, auf den gewartet wird t
.
Dieses unintuitive Verhalten ist der Grund, warum sie Folgendes in die Dokumentation schreiben:
Es wird empfohlen , dass Anwendungen nicht verwenden
wait
,notify
odernotifyAll
aufThread
Instanzen.
Antwort auf den Fragentitel
Auschecken Object#wait(oder JLS (17.2.1. Warten) ):
Ein Thread kann aufwachen, ohne benachrichtigt, unterbrochen oder abgelaufen zu werden, ein sogenanntes falsches Aufwecken. Während dies in der Praxis selten vorkommt, müssen Anwendungen dagegen vorgehen, indem sie auf den Zustand testen, der das Aufwecken des Threads hätte verursachen sollen, und weiterhin warten, wenn der Zustand nicht erfüllt ist.
So können Threads in Java jederzeit aktiviert werden. Ein falsches Aufwachen ist nicht sehr wahrscheinlich , kann aber passieren.