Esta pregunta se publicó en algún sitio. No encontré las respuestas correctas allí, así que lo estoy publicando aquí nuevamente.
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
}
}
Mi consulta no se trata de detener un hilo. Permítame rehacer mi pregunta. La línea A (ver código arriba) inicia un nuevo hilo; y la línea B hacen nula la referencia del hilo. Entonces, la JVM ahora tiene un objeto Thread (que está en estado de ejecución) al que no existe ninguna referencia (como t = nulo en la línea B). Entonces mi pregunta es, ¿por qué este hilo (que ya no tiene referencia en el hilo principal) sigue ejecutándose hasta que el hilo principal se está ejecutando? Según tengo entendido, el objeto del hilo debería haber sido recolectado como basura después de la Línea B. Intenté ejecutar este código durante 5 minutos y más, solicitando Java Runtime para ejecutar GC, pero el hilo simplemente no se detiene.
Espero que tanto el código como la pregunta estén claros esta vez.
child.join()
, tenía una referencia achild
. Si esa referencia (y cualquier otra) no se descarta, el hilo secundario no puede ser GCed.Como se explicó, los subprocesos en ejecución son, por definición, inmunes a GC. El GC comienza su trabajo escaneando las "raíces", que se consideran siempre accesibles; las raíces incluyen variables globales ("campos estáticos" en Java-talk) y las pilas de todos los subprocesos en ejecución (se puede imaginar que la pila de un subproceso en ejecución hace referencia a la
Thread
instancia correspondiente ).Sin embargo, puede convertir un hilo en un hilo "demonio" (ver
Thread.setDaemon(boolean)
). Un subproceso daemon no se recolecta más basura que un subproceso que no es demonio, pero la JVM sale cuando todos los subprocesos en ejecución son demonios. Una forma de imaginarlo es que cada hilo, cuando termina, comprueba si quedan algunos hilos en ejecución que no sean demonios; si no, el hilo de terminación fuerza unaSystem.exit()
llamada, que sale de la JVM (matando los hilos del demonio en ejecución). Este no es un problema relacionado con GC; en cierto modo, los subprocesos se asignan manualmente. Sin embargo, así es como la JVM puede tolerar subprocesos semi-maliciosos. Suele utilizarse paraTimer
instancias.fuente
La JVM tiene una referencia a todos los subprocesos en ejecución.
Ningún hilo (o las cosas a las que se refiere) se recolectará como basura mientras aún se esté ejecutando.
fuente
El subproceso no se recolecta como basura porque hay referencias a los subprocesos que no puede ver. Por ejemplo, hay referencias en el sistema de ejecución.
Cuando se crea el hilo, se agrega al grupo de hilos actual. Puede obtener una lista de subprocesos en el grupo de subprocesos actual, por lo que es otra forma de obtener una referencia a él.
fuente