Diese Frage wurde auf einer Website veröffentlicht. Ich habe dort keine richtigen Antworten gefunden, deshalb poste ich sie hier erneut.
public class TestThread {
public static void main(String[] s) {
// anonymous class extends Thread
Thread t = new Thread() {
public void run() {
// infinite loop
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// as long as this line printed out, you know it is alive.
System.out.println("thread is running...");
}
}
};
t.start(); // Line A
t = null; // Line B
// no more references for Thread t
// another infinite loop
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
System.gc();
System.out.println("Executed System.gc()");
} // The program will run forever until you use ^C to stop it
}
}
Bei meiner Abfrage geht es nicht darum, einen Thread zu stoppen. Lassen Sie mich meine Frage umformulieren. Zeile A (siehe Code oben) startet einen neuen Thread. und Zeile B machen die Thread-Referenz null. Die JVM verfügt nun über ein Thread-Objekt (das sich im laufenden Zustand befindet), auf das kein Verweis vorhanden ist (als t = null in Zeile B). Meine Frage ist also, warum dieser Thread (der im Hauptthread keine Referenz mehr hat) so lange läuft, bis der Hauptthread läuft. Nach meinem Verständnis sollte das Thread-Objekt nach Zeile B durch Müll gesammelt worden sein. Ich habe versucht, diesen Code 5 Minuten und länger auszuführen, wobei Java Runtime aufgefordert wurde, GC auszuführen, aber der Thread stoppt einfach nicht.
Hoffe, dass diesmal sowohl der Code als auch die Frage klar sind.
child.join()
, hatte er einen Verweis aufchild
. Wenn diese Referenz (und eine andere) nicht verworfen wird, kann der untergeordnete Thread nicht gced werden.Wie bereits erläutert, sind laufende Threads per Definition immun gegen GC. Der GC beginnt seine Arbeit mit dem Scannen von "Wurzeln", die als immer erreichbar gelten. Zu den Wurzeln gehören globale Variablen ("statische Felder" in Java-talk) und die Stapel aller laufenden Threads (man kann sich vorstellen, dass der Stapel eines laufenden Threads auf die entsprechende
Thread
Instanz verweist ).Sie können einen Thread jedoch zu einem "Daemon" -Thread machen (siehe
Thread.setDaemon(boolean)
). Ein Daemon-Thread wird nicht mehr mit Müll gesammelt als ein Nicht-Daemon-Thread, aber die JVM wird beendet, wenn alle laufenden Threads Daemon sind. Eine Möglichkeit, sich das vorzustellen, besteht darin, dass jeder Thread beim Beenden prüft, ob noch einige Nicht-Daemon-Threads ausgeführt werden. Wenn nicht, erzwingt der beendende Thread einenSystem.exit()
Aufruf, der die JVM beendet (wodurch die laufenden Daemon-Threads beendet werden). Dies ist kein GC-Problem. In gewisser Weise werden Threads manuell zugewiesen. Auf diese Weise kann die JVM jedoch Semi-Rogue-Threads tolerieren. Dies wird normalerweise fürTimer
Instanzen verwendet.quelle
Die JVM hat einen Verweis auf alle laufenden Threads.
Kein Thread (oder die Dinge, auf die er sich bezieht) wird durch Müll gesammelt, solange er noch ausgeführt wird.
quelle
Der Thread wird nicht durch Müll gesammelt, da Verweise auf die Threads vorhanden sind, die Sie nicht sehen können. Beispielsweise gibt es Referenzen im Laufzeitsystem.
Wenn der Thread erstellt wird, wird er der aktuellen Thread-Gruppe hinzugefügt. Sie können eine Liste der Threads in der aktuellen Thread-Gruppe abrufen. Dies ist eine weitere Möglichkeit, einen Verweis darauf zu erhalten.
quelle