To pytanie zostało opublikowane w jakiejś witrynie. Nie znalazłem tam właściwych odpowiedzi, więc zamieszczam je tutaj ponownie.
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
}
}
Moje zapytanie nie dotyczy zatrzymania wątku. Pozwólcie, że przeformułuję moje pytanie. Linia A (patrz kod powyżej) rozpoczyna nowy wątek; i Linia B sprawiają, że odwołanie do wątku jest puste. Tak więc maszyna JVM ma teraz obiekt wątku (który jest uruchomiony), do którego nie istnieje żadne odniesienie (jako t = null w wierszu B). Moje pytanie brzmi więc, dlaczego ten wątek (który nie ma już odniesienia w głównym wątku) działa dalej, dopóki nie zostanie uruchomiony główny wątek. Zgodnie z moim zrozumieniem obiekt wątku powinien zostać usunięty po linii B. Próbowałem uruchomić ten kod przez 5 minut i dłużej, żądając Java Runtime do uruchomienia GC, ale wątek po prostu się nie zatrzymuje.
Mam nadzieję, że tym razem zarówno kod, jak i pytanie są jasne.
child.join()
, miał odniesienie dochild
. Jeśli to odwołanie (i dowolne inne) nie zostanie odrzucone, wątek podrzędny nie może zostać GCed.Jak wyjaśniono, działające wątki są z definicji odporne na GC. GC rozpoczyna swoją pracę od skanowania „korzeni”, które uważa się za zawsze osiągalne; korzenie zawierają zmienne globalne („pola statyczne” w języku Java) i stosy wszystkich działających wątków (można sobie wyobrazić, że stos działającego wątku odwołuje się do odpowiedniej
Thread
instancji).Możesz jednak uczynić z wątku wątek „demona” (zobacz
Thread.setDaemon(boolean)
). Wątek demona nie jest bardziej zbierany jako śmieci niż wątek niebędący demonem, ale JVM kończy działanie, gdy wszystkie uruchomione wątki są demonami. Można sobie wyobrazić, że każdy wątek, po zakończeniu, sprawdza, czy pozostały jakieś wątki, które nie są uruchomione przez demona; jeśli nie, wątek kończący wymuszaSystem.exit()
wywołanie, które opuszcza JVM (zabija działające wątki demona). To nie jest kwestia związana z GC; w pewnym sensie wątki są przydzielane ręcznie. Jednak w ten sposób JVM może tolerować częściowo nielegalne wątki. Jest to zwykle używane wTimer
przypadku instancji.źródło
JVM ma odniesienie do wszystkich uruchomionych wątków.
Żaden wątek (ani rzeczy, do których się odnosi) nie zostanie usunięty z pamięci, gdy będzie on nadal działał.
źródło
Wątek nie jest usuwany bez pamięci, ponieważ istnieją odwołania do wątków, których nie można zobaczyć. Na przykład istnieją odwołania w systemie wykonawczym.
Tworzony wątek jest dodawany do bieżącej grupy wątków. Możesz uzyskać listę wątków w bieżącej grupie wątków, więc jest to inny sposób na uzyskanie odniesienia do niej.
źródło