2011-12-29 8 views
27

Hipotético escenario:
Tengo un hilo daemon responsable de algunas E/S, el hilo principal termina y vuelve, y la JVM decide terminar mi hilo daemon.¿Cómo termina JVM los hilos daemon? o Cómo escribir hilos daemon que terminan correctamente

¿Cómo lo hace? ¿Interrumpir? ¿Finalizar? ¿Cómo puedo codificar mi hilo daemon para que reaccione correctamente cuando se termine?

+1

¿Miraste el código fuente? –

+2

@StephenC Eso no se me había ocurrido, y definitivamente daría una respuesta definitiva (aunque no innecesariamente útil). Personalmente, sin embargo, no soy lo suficientemente valiente como para intentarlo y no espero que nadie más lo haga. –

+0

Bien, déjame ser más explícito. La mejor manera de responder a una pregunta como esta es mirar el código fuente, o al menos el código Java. En general, es fácil de leer y bien comentado.(Y no entiendo cómo una respuesta definitiva a una pregunta es menos útil que una no definitiva ... especialmente si * usted * fue la persona que leyó el código!) –

Respuesta

10

acabo escribió el siguiente código como una prueba:

public class DaemonThreadPlay { 
    public static void main(String [] args) { 
     Thread daemonThread = new Thread() { 
      public void run() { 
       while (true) { 
        try { 
         System.out.println("Try block executed"); 
         Thread.sleep(1000l); 
        } catch (Throwable t) { 
         t.printStackTrace(); 
        } 
       } 
      } 

      @Override 
      public void finalize() { 
       System.out.println("Finalize method called"); 
      } 
     }; 
     daemonThread.setDaemon(true); 
     daemonThread.start(); 

     try { 
      Thread.sleep(2500l); 
     } catch (Throwable t) { 
      //NO-OP 
     } 
    } 
}  

puse los puntos de interrupción en el bloque catch del hilo de utilidad y en el método de finalización. Ninguno de los puntos de corte se alcanzó aunque se ejecutó el bloque try. Obviamente, este código tiene problemas de sincronización/sincronización, pero creo que podemos concluir con seguridad que los hilos daemon no se interrumpen al apagarlos ni se invocan necesariamente sus métodos finalize().

Siempre se puede añadir un gancho de cierre a la JVM Duración:

Thread shutdownHook = ... // construct thread that somehow 
          // knows about all the daemon threads 
Runtime.getRuntime().addShutdownHook(shutdownHook); 

su gancho de cierre se puede hacer, obviamente, cualquier tarea que se requieren para un cierre "agraciado".

+1

Me gusta el gancho de apagado. –

+0

Encontrado [este] (http://stackoverflow.com/questions/1323408/get-a-list-of-all-threads- current-runing-in-java/3018672 # 3018672) cuando se buscan formas de obtener hilos activos . Tendría que iterar sobre la matriz para verificar al menos una cadena de usuario.
Creo que un gancho de apagado es la mejor solución, nunca antes se había enterado de esta funcionalidad. Creo que mantendré una referencia a mi gancho de cierre en mi clase principal, y mantendré una colección de mis hilos daemon en el gancho de cierre. Entonces puedo simplemente interrumpirlos a todos. Intentaré publicar mi código una vez que lo implemente. –

+2

Si llama '' System.gc() 'explícitamente y la opción JVM' -XX: + DisableExplicitGC' no está configurada, entonces el hilo daemon saldrá. Esto significa que Garbage Collector es responsable de cerrar los subprocesos de daemon una vez finalizados todos los subprocesos de usuario. – George

4

AFAIK, los hilos Daemon no son realmente para el trabajo de E/S de transmisión principal. Si se completan todos los subprocesos, JVM puede cerrar todos los subprocesos de daemon de forma abrupta. La posible solución para su requerimiento será crear un ExecutorService, como a continuación:

ExecutorService execPool = Executors.newSingleThreadExecutor(new ThreadFactory() { 

    @Override  
    public Thread newThread(Runnable runnable) {  
     Thread thread = Executors.defaultThreadFactory().newThread(runnable); 
     thread.setDaemon(true); 
     return thread;  
    } 
}); 

método invoke ExecutorService apagado del gancho de cierre.

Runtime.getRuntime().addShutdownHook(....) 
+0

su nuevo método Thread realmente crea una nueva fábrica de hilos cada vez. una llamada a 'Executors.defaultThreadFactory()' solo devuelve un 'nuevo DefaultThreadFactory()' – benez

1

uso interrupción y unirse a:

class Daemon extends Thread { 
    public void run() { 
     while (true) { 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       System.out.println(e); 
       break; 
      } 
     } 
     System.out.println("exit run()"); 
    } 
} 
public class So8663107 { 
    public static void main(String[] arguments) throws InterruptedException { 
     System.out.println(Thread.activeCount()); 
     Daemon daemon = new Daemon(); 
     daemon.setDaemon(true); 
     daemon.start(); 
     Thread.sleep(2500); 
     System.out.println(Thread.activeCount()); 
     daemon.interrupt(); 
     daemon.join(); 
     System.out.println(Thread.activeCount()); 
    } 
} 
+3

No creo que haya entendido la pregunta. No quiero interrumpir mis hilos de daemon. Quiero saber cómo la JVM los termina y cómo lidiar con eso. –

+0

lo siento, estaba intentando responder: "¿Cómo puedo codificar mi hilo daemon para que termine con elegancia?" –

+0

Ok, he editado la pregunta –

5

creo que usted no entiende lo que es un hilo de utilidad es.

Ver what is a daemon thread in java

En resumen, que básicamente significa que un hilo de utilidad no debería estar haciendo cualquier E/S o la celebración de cualquier recurso. Si estás contraviniendo esta regla básica, entonces tu hilo no califica como un hilo daemon.

Añadir un gancho de desconexión es la forma estándar de garantizar que se invoque su código antes de la terminación de JVM, pero incluso esto no está 100% garantizado; su JVM podría fallar, dejando el sistema operativo para ordenar los recursos de una manera que protege el sistema operativo, pero es muy probable que deje su aplicación en un estado inconsistente/erróneo.

Los mecanismos de punto de control y recuperación se remontan a los primeros días del software (sistemas operativos y operaciones por lotes, por ejemplo) y desafortunadamente, esta rueda se reinventa porque no hay un enfoque "bala de plata" que aborde este problema de una manera genérica suficiente.

+0

¿Cuál es la base de la afirmación de que los hilos Daemon no deberían estar haciendo IO o teniendo recursos? – ykaganovich

+0

Siga el enlace proporcionado y obtendrá algunas ideas. – user924272

+1

lo siento, no estoy de acuerdo. Siempre y cuando se entienda que un hilo de Daemon se puede matar a mitad del procesamiento, no hay peligro, a menos que sepa algo acerca de las fugas de recursos de Java que yo no sé. – ykaganovich