java multithreading garbage-collection

Java Thread Garbage recopilada o no



multithreading garbage-collection (4)

Como se explicó, los hilos ejecutables son, por definición, inmunes a GC. El GC comienza su trabajo escaneando "raíces", que se consideran siempre alcanzables; Las raíces incluyen variables globales ("campos estáticos" en Java-talk) y las pilas de todos los hilos en ejecución (se puede imaginar que la pila de un hilo en ejecución hace referencia a la instancia correspondiente de Thread ).

Sin embargo, puede hacer que un hilo sea un hilo "daemon" (vea Thread.setDaemon(boolean) ). Un subproceso de daemon no se recolecta más que un subproceso que no sea de daemon, pero la JVM se cierra cuando todos los subprocesos en ejecución son daemon. Una forma de imaginarlo es que cada subproceso, cuando termina, comprueba si quedan algunos subprocesos que no son de demonio; de lo contrario, la System.exit() terminación fuerza una System.exit() a System.exit() , que sale de la JVM ( System.exit() hilos del daemon en ejecución). Esto no es un problema relacionado con GC; de alguna manera, los hilos se asignan manualmente. Sin embargo, así es como la JVM puede tolerar subprocesos semi-rogue. Esto se usa típicamente para instancias de Timer .

Esta pregunta fue publicada en algún sitio. No encontré las respuestas correctas allí, así que lo vuelvo a publicar aquí.

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 trata de detener un hilo. Permítame rehacer mi pregunta. La línea A (ver el código anterior) inicia un nuevo hilo; y la línea B hace que la referencia del hilo sea nula. Entonces, la JVM ahora tiene un objeto de subproceso (que está en estado de ejecución) para el que no existe 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 se ejecuta el hilo principal? Según entiendo, el objeto thread debería haber sido recogido basura después de la línea B. Intenté ejecutar este código durante 5 minutos y más, solicitando a Java Runtime que ejecute GC, pero el hilo simplemente no se detiene.

Espero que tanto el código como la pregunta estén claros esta vez.


El subproceso no es basura recolectada porque hay referencias a los subprocesos que no puede ver. Por ejemplo, hay referencias en el sistema de tiempo de ejecución.

Cuando se crea el subproceso, se agrega al grupo de subprocesos actual. Puede obtener una lista de subprocesos en el grupo de subprocesos actual, de modo que esa es otra forma de obtener una referencia.


La JVM tiene una referencia a todos los subprocesos en ejecución.

Ningún subproceso (o las cosas a las que hace referencia) se recolectará como basura mientras aún se está ejecutando.


Un subproceso en ejecución se considera una llamada raíz de recolección de basura y es una de esas cosas que impide que las cosas se recolecten como basura. Cuando el recolector de basura determina si su objeto es " reachable " o no, siempre lo hace usando el conjunto de raíces del recolector de basura como puntos de referencia.

Considere esto, ¿por qué su hilo principal no es basura recogida, nadie está haciendo referencia a eso tampoco.