Pregunta

tengo este bastante simple pregunta acerca de la ThreadPoolExecutor. Tengo la siguiente situación: Tengo que consumir los objetos de una cola, crear las tareas de los trabajadores apropiados para ellos y someterlos a la ThreadPoolExecutor. Esto es bastante simple. Pero dentro de un escenario de inactividad muchos los trabajadores pueden estar en cola para su ejecución. Dado que una de las tareas puede ser que funcione durante una hora, y quiero un cierre rápido relativly agraciada de la aplicación quiero descartar todas las tareas en cola desde el ThreadPoolExecutor mientras que las tareas de procesamiento ya deben completarse con normalidad.

La documentación ThreadPoolExecutor tiene un eliminar método (), pero sólo permite a tareas específicas que deben eliminarse. purga () sólo funciona para las tareas futuras ya cancelados. Mi idea era limpiar la cola de espera de todas las tareas en cola. El ThreadPoolExecutor proporciona acceso a esta cola interna, pero la documentación indica:

  

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 es fuertemente   desanimado.

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

  

Dos métodos suministrados,   eliminar (java.lang.Runnable) y de purga ()   están disponibles para ayudar a almacenar   la recuperación cuando un gran número de   tareas en cola se vuelven cancelada.

¿Cómo? Claro, puedo mantener una lista de todas las tareas que presenté al ejecutor y en un caso de parada i iterar sobre todas las entradas y eliminarlos de la ThreadPoolExecutor con el método remove () ... pero ... vamos, esta es una pérdida de memoria y una molestia para mantener esta lista. (Extracción de tareas ya ejecutados por ejemplo)

aprecio ninguna pista o soluciones!

¿Fue útil?

Solución

Ha considerado envolviendo el ExecutorService? Crear un

CleanShutdownExecutorService implements Executor 

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

Otros consejos

Yo solía trabajar en una aplicación con hilos de ejecución larga. Hacemos esto al apagar el equipo,

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, se añade la lista de nuevo a la piscina, así que no se pierde ningún trabajo.

ExecutorService. shutdown () no está haciendo lo suficiente y ExecutorService.shutdownNow () está haciendo demasiado supongo que tienes que escribir algo en el medio:. recordar todas las tareas presentadas y eliminarlos manualmente después (o antes) llamando shutdown()

Esta es una vieja pregunta, pero en caso de que esto ayude a alguien más: puede establecer un valor lógico volátil cuando se llama a shutdown (), y tienen cada tarea presentada por terminado si eso booleano se establece antes de comenzar realmente. Esto permitirá tareas que realmente han comenzado a completar, pero evitará que las tareas en cola de comenzar su actividad real.

La respuesta de Bombe es exactamente lo que quiere. shutdownNow() todo se detiene mediante el arma nuclear y allanar enfoque. Este es el mejor que puede hacer, por debajo de la subclasificación de la implementación de ThreadPoolExecutor que está utilizando.

Puede intentar allowCoreThreadTimeOut(true);

Se puede crear su propia cola de tareas y pasarlo a ThreadPoolExecutor constructor:

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

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

queue.clear();

Una solución loca y sucio que podría trabajar (pensamiento no real a través de o probado) sería para sobrescribir el interrupt() de sus WorkerTasks que sólo en caso de que se establece un valor global de negarse a apagarse cuando interrupt() se les pidió por shutdownNow () .

Esto debería permitir el uso de shutdownNow() no?

Informe a su grupo de subprocesos para apagar, getQueue, para cada uno-el resultado en Runnables individuales, retire cada Ejecutable utilizando el método remove. Dependiendo del tipo de cola, que podría ser capaz de detener los elimina temprana basada en los valores de retorno.

Básicamente, este es agarrar la cola y la limpieza, sólo la limpieza a través de los métodos que trabajan. En vez de recordar manualmente todas las presentaciones, utiliza el hecho de la agrupación de hebras ya tiene a recordar todas las presentaciones. Sin embargo, es probable que necesite para hacer una copia defensiva de la cola, ya que creo que es una vista en vivo, y por lo tanto la eliminación, probablemente causar una excepción de la modificación concurrente si estuviera iterando / para-eaching sobre la visualización en directo.

No awaitTermination(long timeout, TimeUnit unit) trabajo después de la parada?

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top