2012-10-10 86 views
9

Tengo una serie de tareas dentro de un TheadPoolExecutor. Tengo un botón de detención en mi interfaz que debe terminar todos los hilos dentro de ThreadPoolExecutor inmediatamente. Estoy buscando una manera de hacerlo. (sin shutDown() o shutDownNow()).Cómo forzar a terminar a todos los trabajadores en ThreadPoolExecutor inmediatamente

Gracias

+0

¿Por qué no (o no) utiliza 'shtudown()' o 'shutdownNow()'? Esa es la manera de hacerlo. – Gray

+0

Porque debe esperar a que las tareas actuales finalicen antes de terminar los subprocesos. Por lo tanto, no mata los hilos inmediatamente. – deadlock

+0

'shutdown()' espera a que finalicen las tareas actuales. Ese es el punto de eso. – Gray

Respuesta

10

No puede matar con seguridad los hilos inmediatamente. En su lugar, las tareas deberían respetar las interrupciones y detenerse cuando se interrumpan. Si usa ThreadPoolExecutor.shutdownNow(), se interrumpirán todas las tareas en ejecución.

La única alternativa es que los hilos en un proceso separado emitan una señal para matar el proceso.

6

El shutdown() solo hará que el ThreadPoolExecutor rechace todas las tareas nuevas enviadas, y eliminará de la cola (si el ThreadPool es un ejecutor de colas sin límites) las tareas pendientes. El shutdownNow() hará exactamente lo mismo, y también llamará al método interrupt() del Thread. Por lo tanto, en el método de run(), debe manejarlo correctamente:

try { 
    Thread.sleep(1000); 
} catch (InterruptedException ie) { 
    // Handle the exception, and close resources. 
} 
+1

'shutdown()' no vacía la cola. – The111

+0

@ The111 para vaciar la cola, puede usar purge() – WiredCoder

2

Si puede utilizar Callable s en lugar de Runnable s en sus hilos se podría tratar de llamar someTask.cancel() para deshacerse de las tareas en ejecución en el momento de shutdownNow() llamada.

Tenga en cuenta que no he probado esto, por lo que no puedo garantizar que funcione como usted quisiera, pero a juzgar por la descripción de javadoc vale la pena intentarlo.

2

Pregunta anterior, pero creo que se puede ampliar ThreadPoolExecutor para capturar la referencia de ejecución de subprocesos en beforeExecute(). Cuando se llama a shutdownNow() puede detener() todos los subprocesos en ejecución. Aunque le recomiendo que confíe en isinterrupted() en sus tareas.

Código de ejemplo ->

public class KillableThreadPoolExecutor extends ThreadPoolExecutor { 

    private final Map<Runnable, Thread> executingThreads; 

    public KillableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, String threadNamePrefix) { 
     super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new YoungMemorySafeLinkedBlockingQueue<Runnable>(), ThreadFactories.create(threadNamePrefix)); 
     executingThreads = new HashMap<>(maximumPoolSize); 
    } 

    @Override 
    protected synchronized void beforeExecute(Thread t, Runnable r) { 
     super.beforeExecute(t, r); 
     executingThreads.put(r, t); 
    } 

    @Override 
    protected synchronized void afterExecute(Runnable r, Throwable t) { 
     super.afterExecute(r, t); 
     if(executingThreads.containsKey(r)) { 
      executingThreads.remove(r); 
     } 
    } 

    @Override 
    public synchronized List<Runnable> shutdownNow() { 
     List<Runnable> runnables = super.shutdownNow(); 
     for(Thread t : executingThreads.values()) { 
      t.stop(); 
     } 
     return runnables; 
    } 
} 
2

ThreadPoolExecutor es un ExecutorService. No puede detener todos los hilos en ExecutorService con los métodos shutdown() o shutdownNow(). Tienes que llamar a shutdown(), awaitTermination() y shutdownNow() métodos en una secuencia de apagado correcto citado por la documentación de Oracle page

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(); 
    } 
} 

Otras opciones:

  1. invokeAll()
  2. CountDownLatch
  3. iterar a través de todos los Future.get() para todos Callable tareas para lograr el mismo propósito.
Cuestiones relacionadas