thread hilos example create java multithreading threadpool executorservice executor

java - hilos - Eliminar todas las tareas en cola de un ThreadPoolExecutor



thread java 8 (10)

Tengo esta pregunta bastante simple sobre el ThreadPoolExecutor . Tengo la siguiente situación: tengo que consumir objetos de una cola, crear las tareas de trabajo adecuadas para ellos y enviarlos al ThreadPoolExecutor. Esto es bastante simple. Pero dentro de un escenario de cierre, muchos trabajadores pueden estar en cola para su ejecución. Dado que una de esas tareas podría estar ejecutándose durante una hora, y quiero un cierre relativamente rápido y elegante de la aplicación, deseo descartar todas las tareas en cola del ThreadPoolExecutor mientras que las tareas que ya están en proceso se deben completar normalmente.

La documentación de ThreadPoolExecutor tiene un método remove() pero solo permite eliminar tareas específicas. purge() solo funciona para tareas futuras ya canceladas. Mi idea era borrar la cola que contiene todas las tareas en cola. ThreadPoolExecutor proporciona acceso a esta cola interna, pero la documentación dice:

El método getQueue () permite el acceso a la cola de trabajo para fines de monitoreo y depuración. El uso de este método para cualquier otro propósito está fuertemente desaconsejado.

Así que agarrar esta cola y borrarla no es una opción. Además, este fragmento de la documentación dice:

Dos métodos suministrados, remove (java.lang.Runnable) y purge () están disponibles para ayudar en la recuperación de almacenamiento cuando se cancelan grandes cantidades de tareas en cola.

¿Cómo? Claro, puedo mantener una lista de todas las tareas que envié al ejecutor y, en un caso de apagado, repaso todas las entradas y las elimino de ThreadPoolExecutor con el método remove () ... pero ... vamos, esto es un pérdida de memoria y una molestia para mantener esta lista. (Eliminando tareas ya ejecutadas por ejemplo)

¡Aprecio cualquier consejo o solución!


¿Has considerado envolver el servicio de ejecución? Crear un

CleanShutdownExecutorService implements Executor

que delega todas las llamadas a otro Ejecutor, pero mantiene los futuros en una lista propia. CleanShutdownExecutorService puede tener un método cancelRemainingTasks () que llama a shutdown (), luego cancela (false) en todos los futuros en su lista.


¿No awaitTermination(long timeout, TimeUnit unit) funcione después del apagado?

executor.shutdown (); executor.awaitTermination (60, TimeUnit.SECONDS)



Dígale a su grupo de subprocesos que apague, obtengaQueue, para cada resultado en Runnables individuales, elimine cada Runnable utilizando el método de eliminación. Dependiendo del tipo de cola, es posible que pueda detener las eliminaciones anticipadamente en función de los valores de retorno.

Básicamente, esto es agarrar la cola y borrarla, solo limpiarla a través de los métodos que funcionan. En lugar de recordar manualmente todos los envíos, usa el hecho de que el grupo de hilos ya tiene que recordar todos los envíos. Sin embargo, es probable que necesite hacer una copia defensiva de la cola, ya que creo que es una vista en vivo, y por lo tanto, la eliminación causaría una excepción de modificación concurrente si estuviera iterando / para cada uno en la vista en vivo.


Esta es una pregunta antigua, pero en caso de que esto ayude a alguien más: usted podría establecer un booleano volátil cuando llame a shutdown (), y hacer que cada tarea enviada termine si ese booleano está configurado antes de comenzar realmente. Esto permitirá que las tareas que realmente han comenzado a completarse, pero evitará que las tareas en cola inicien su actividad real.


La respuesta de Bombe es exactamente lo que quieres. shutdownNow() detiene todo usando el enfoque nuclear y allanar . Esto es lo mejor que puede hacer, ThreadPoolExecutor subclasificar la implementación de ThreadPoolExecutor que está usando.


Podría crear su propia cola de tareas y pasarla al constructor ThreadPoolExecutor :

int poolSize = 1; // number of threads BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(); Executor executor = new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS, queue);

Cuando borra la cola en algún lugar de su código, las tareas restantes no se ejecutarán:

queue.clear();


Puedes probar allowCoreThreadTimeOut(true);


Solía ​​trabajar en una aplicación con hilos de larga ejecución. Hacemos esto en el cierre,

BlockingQueue<Runnable> queue = threadPool.getQueue(); List<Runnable> list = new ArrayList<Runnable>(); int tasks = queue.drainTo(list);

La lista se guarda en un archivo. En el inicio, la lista se agrega de nuevo al grupo para que no perdamos ningún trabajo.


Una solución loca e impura que podría funcionar (no pensada o probada) sería sobreescribir la interrupt() de sus Tareas de trabajo, que solo en caso de que se establezca algún valor global se nieguen a apagarse cuando se llame a interrupt() mediante shutdownNow ( ).

Eso debería permitirte usar shutdownNow() ¿no?