2012-05-17 13 views
5

Ayúdeme a encontrar el motivo de la fuga de subprocesos en el código siguiente. El TestThread no obtiene basura recolectada incluso después de que se haya completado la ejecución() (verificada desde la sentencia de impresión con consolas) y el método principal ha salido (verificado desde la declaración de impresión y la herramienta de creación de perfiles).Por qué UserThread se ejecuta con ScheduleExecutorService no obtiene basura recolectada

Sin embargo, TestThread obtiene basura recolectada si está configurada como Daemon Thread, es decir, t.setDaemon(true). El siguiente código es solo un código de muestra que ilustra el problema en mi aplicación. Intento utilizar alguna clase de planificación preexistente (que fue diseñada por otra persona usando ScheduledExecutorService). Noté que cuando sigo programando múltiples Runnable s con la clase, los hilos creados nunca se recogen basura.

public class ThreadTest { 

    static void runThreadWithExecutor() { 
    final String name = "TestThread"; 
    ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(
     new ThreadFactory() { 
      @Override 
      public Thread newThread(Runnable r) { 
      Thread t = new Thread(r, name); 
      t.setDaemon(false); 
      return t; 
      } 
     }); 

    ses.schedule(new Runnable() { 
     @Override 
     public void run() { 
      System.out.println("entered " + name); 
      System.out.println("exiting " + name); 
     }}, 
     2, 
     TimeUnit.SECONDS); 
    } 

    public static void main(String[] args) throws InterruptedException { 
    System.out.println("entered main"); 
    runThreadWithExecutor(); 
    Thread.sleep(5000); 
    System.out.println("exiting main"); 
    } 
} 

Respuesta

5

Esto se debe al hecho de que no está llamando shutdown() en su servicio ejecutor después de haber programado su último trabajo:

ses.schedule(...); 
// this stops any management threads but existing jobs will still run 
ses.shutdown(); 

acabo añade la llamada shutdown() a su código y que sale multa. Esto es verdad de todos ExecutorService s. Sin el cierre, el grupo de subprocesos continúa esperando a que se envíen más trabajos y nunca se envía un GC.

Consulte la respuesta de @ John a continuación para obtener más detalles.

3

@Gray es correcto con su evaluación Me imagino que agregué el motivo por el cual es correcto. ExecutorService es un grupo de subprocesos que reutilizará los subprocesos.

A diferencia de new Thread(runnable).start(); cuando el método de ejecución completa el hilo se completa y luego será GC'd. Cuando un Executor Runnable completa el hilo se quedará allí y esperará a que se envíe y use otra tarea ejecutable. Entonces, al cerrar, le está diciendo al ejecutor que finalice todos los subprocesos en el grupo de subprocesos.

Para responder a su última parte. Configurarlo en daemon funciona solo porque no hay otros hilos (no demoníacos) en ejecución. Si su aplicación inició algún otro subproceso no demoníaco, el subproceso Ejecutor continuará. Recuerde que un hilo de daemon se eliminará cuando solo se estén ejecutando subprocesos de daemon.

+2

Buena información John. Un ajuste. 'shutdown()' no finaliza todos los subprocesos en el grupo de subprocesos hasta que todos los trabajos ya se hayan enviado. – Gray

+0

@Gray Buen punto –

+0

Gracias chicos. Aunque inicialmente seleccioné esto como mi respuesta aceptada, más tarde escogí a Gray porque esta respuesta no se explica por sí misma sin la de Gray. Esta respuesta, sin embargo, me dio la explicación completa necesaria para modificar el código con confianza :) ¡y funciona! – Kes115

Cuestiones relacionadas