2012-05-08 26 views
33

Siempre que llamo al shutdownNow() o shutdown(), no se apaga. Leí algunos hilos en los que decía que el cierre no está garantizado. ¿Alguien puede proporcionarme una buena forma de hacerlo?¿Cómo cerrar un ExecutorService?

+0

Por favor marque la respuesta correcta como aceptadas – gonephishing

Respuesta

74

El patrón típico es:

executorService.shutdownNow(); 
executorService.awaitTermination(); 

Al llamar shutdownNow, el ejecutor (generalmente) tratan de interrumpir los hilos que gestiona. Para que el cierre sea más ordenado, debe detectar la excepción interrumpida en los hilos o verificar el estado interrumpido. Si no lo haces, tus hilos se ejecutarán para siempre y tu ejecutor nunca podrá apagarse. Esto se debe a que la interrupción de subprocesos en Java es un proceso colaborativo (es decir, el código interrumpido debe hacer algo cuando se le solicita detenerse, no el que interrumpe el código).

Por ejemplo, el siguiente código imprime Exiting normally.... Pero si comenta la línea if (Thread.currentThread().isInterrupted()) break;, imprimirá Still waiting... porque los hilos dentro del ejecutor aún se están ejecutando.

public static void main(String args[]) throws InterruptedException { 
    ExecutorService executor = Executors.newFixedThreadPool(1); 
    executor.submit(new Runnable() { 

     @Override 
     public void run() { 
      while (true) { 
       if (Thread.currentThread().isInterrupted()) break; 
      } 
     } 
    }); 

    executor.shutdownNow(); 
    if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) { 
     System.out.println("Still waiting..."); 
     System.exit(0); 
    } 
    System.out.println("Exiting normally..."); 
} 

Alternativamente, podría ser escrita con un InterruptedException así:

public static void main(String args[]) throws InterruptedException { 
    ExecutorService executor = Executors.newFixedThreadPool(1); 
    executor.submit(new Runnable() { 

     @Override 
     public void run() { 
      try { 
       while (true) {Thread.sleep(10);} 
      } catch (InterruptedException e) { 
       //ok let's get out of here 
      } 
     } 
    }); 

    executor.shutdownNow(); 
    if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) { 
     System.out.println("Still waiting..."); 
     System.exit(0); 
    } 
    System.out.println("Exiting normally..."); 
} 
+0

Cómo sabe si también inicia el apagado 'Thread.interrupt()', desde la API de Java no lo hace parece que 'shutdown' interrumpe los hilos? – Bionix1441

+1

@ Bionix1441 No, no es así. 'shutdownNow' hace sin embargo. – assylias

15

La mejor manera es lo que realmente tenemos en el javadoc que es:

Los siguientes cierra método abajo de un ExecutorService en dos fases, primero llamando al shutdown para rechazar tareas entrantes, y luego llamando al shutdownNow, si es necesario, para cancelar las tareas persistentes:

void shutdownAndAwaitTermination(ExecutorService pool) { 
    pool.shutdown(); // Disable new tasks from being submitted 
    try { 
     // Wait a while for existing tasks to terminate 
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { 
      pool.shutdownNow(); // Cancel currently executing tasks 
      // Wait a while for tasks to respond to being cancelled 
      if (!pool.awaitTermination(60, TimeUnit.SECONDS)) 
       System.err.println("Pool did not terminate"); 
     } 
    } catch (InterruptedException ie) { 
     // (Re-)Cancel if current thread also interrupted 
     pool.shutdownNow(); 
     // Preserve interrupt status 
     Thread.currentThread().interrupt(); 
    } 
} 
Cuestiones relacionadas