2009-07-31 11 views
9

De acuerdo con Java Concurrency in Practice de Brian Goetz JVM no puede salir hasta que todos los subprocesos (no demoníacos) hayan finalizado, por lo que si no se cierra un Executor podría evitar que la JVM salga.Cómo cerrar todos los ejecutores al salir de una aplicación?

I.e. System.exit (0) no funciona necesariamente como se espera si hay ejecutores alrededor. Parecería necesario poner algún tipo de

public void stop() { exec.shutdown() } 

métodos para todas las clases que contienen los ejecutores, y luego se les llama cuando la aplicación está a punto de terminar. ¿Es esta la única manera, o hay algún tipo de atajo para cerrar todos los ejecutores?

+0

Estaba confundiendo Executor con Runnable. Eliminé mi respuesta ya que no tiene mucho sentido. @skaffman tiene mi voto. –

Respuesta

14

No hay atajo para hacer todo, no. Además, probablemente debería llamar al shutdownNow() en lugar de shutdown(), de lo contrario, podría estar esperando un momento.

Lo que podría hacer, supongo, es cuando crea el ejecutor y lo registra en un lugar central. Luego, cuando se apaga, simplemente llame al shutdown() en ese objeto central, que a su vez podría terminar con cada uno de los ejecutores registrados.

Si usa Spring, puede aprovechar sus beans de fábrica que crean y administran los ejecutores por usted. Eso incluye cerrarlos elegantemente cuando la aplicación se cierra, y le ahorra tener que administrarlos usted mismo.

+0

El registro central parece ser una opción razonable. Es gracioso que java.util.concurrent no incluya tales. –

+0

También es una pena que los ejecutores sean solo un montón de estática, que hace que sea difícil esconderlo detrás de una interfaz de registro sin duplicar varias docenas de firmas de métodos. – skaffman

+0

También estoy enfrentando un problema similar. No estoy usando explícitamente ScheduledThreadPoolExecutor. Entonces no tengo ninguna referencia central a lo mismo. En tal caso, ¿cómo acceder a estos grupos de hilos? Estoy tratando de cerrarlos con gracia en el método ContextDestroyed – DecKno

0

Probablemente quiso decir que JVM no puede detenerse por sí solo hasta que los hilos no daimoniales hayan terminado. Es como ejecutar una clase simple desde comandos como java SomeClass y después de la ejecución del método principal, JVM se detiene.

System.exit es un comando de terminación JVM, incluso si los hilos daemon se están ejecutando JVM se cerrará.

+1

Según escribió Goetz, los subprocesos * nondaemon * pueden impedir que JVM salga. En realidad, he experimentado esto. El depurador muestra que la aplicación puede interferir con el sistema.exit (0) infinitamente, pero parece ser un comportamiento no determinista. Por lo general, no se atasca, pero a veces lo hace. –

5

También puede proporcionar una implementación de ThreadFactory que marque los hilos creados como hilos daemon. Prefiero un mecanismo de apagado limpio (con métodos de ciclo de vida), pero hay casos en los que no necesita garantías sobre el estado/finalización de tareas incompletas cuando esto puede ser apropiado.

+0

Gracias por señalar esta opción. En realidad, algunos de mis ejecutores deberían ser hilos daemon, simplemente resultan ser no demoníacos porque eso es lo que Executors.newXXXExecutor(): s realiza de forma predeterminada. –

7

De forma predeterminada, un ejecutor solo creará subprocesos no daemon. Puede anular eso suministrando al Ejecutor su propia ThreadFactory. He aquí un ejemplo:

class DaemonThreadFactory implements ThreadFactory { 
    public Thread newThread(Runnable r) { 
    Thread t = new Thread(r); 
    t.setDaemon(true); 
    return t; 
    } 
} 

Tenga cuidado, sin embargo, porque la JVM salir de inmediato incluso si estos hilos están ocupados haciendo un trabajo útil!

8

decorar el ejecutor con com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService

@Beta 
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, 
             long terminationTimeout, 
             TimeUnit timeUnit) 

Convierte el ThreadPoolExecutor dada en un ExecutorService que sale cuando la solicitud está completa. Lo hace mediante el uso de subprocesos daemon y agregando un gancho de apagado para esperar su finalización.

Esto es principalmente para grupos de hilos fijos. Ver Executors.newFixedThreadPool (int).

Cuestiones relacionadas