2012-09-24 21 views
9

Tengo una tarea que me obliga a programar tareas y eliminarlas cuando ocurre un determinado evento. Estoy usando un ScheduledThreadPoolExecutor para programar las tareas, eso es bastante sencillo. Pero, encontré dos formas de cancelar los artículos pendientes, ambos se ven un poco extraños.Cómo cancelar elementos pendientes de un ScheduledThreadPoolExecutor?

Tengo curiosidad por si alguno de ellos tiene calidad de producción. Si ninguno de ellos, ¿qué sugieres?

Aquí es un esqueleto de lo que hago:

private final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1); 

public void doStuff() { 
    //... 
    scheduler.schedule(new Runnable() {/*...*/}, 10, TimeUnit.MILISECONDS) 
} 

public void actOnEvent() { 
    cancelPendingItems(); 
    doMoreStuff(); 
} 

public void cancelPendnigItems() { 
    // TODO implement me 
} 

Este es el candidato 1:

public void cancelPendingItems() { 
    scheduler.getQueue().clear(); 
} 

Ésta es candidato 2:

public void cancelPendingItems() { 
    for (Runnable task : scheduler.getQueue()) { 
     scheduler.remove(task); 
    } 
} 

Ambos se ven como un truco para porque dependen de la propiedad ScheduledThreadPoolExecutor.queue que no está especificada en la interfaz ScheduledExecutor . Estoy un poco preocupado de que pueda violar una invariante de ScheduledThreadPoolExecutor y lo detectaré demasiado tarde.

Entonces, ¿van a hacer estos fragmentos lo que yo quiero que hagan? ¿Hay alguna forma mejor/más limpia de hacerlo?

Respuesta

4

me gustaría utilizar un List<Future>:

private final List<Future> futures = ... 

public void doStuff() { 
    futures.add(scheduler.schedule(new Runnable() {/*...*/}, 10, 
     TimeUnit.MILISECONDS)); 
} 

public void cancelPendingItems() { 
    for(Future future: futures) 
     future.cancel(true); 
    futures.clear(); 
} 
+1

Gracias! Afortunadamente, se ajusta a mi problema real porque no hay demasiadas tareas posibles, por lo que esta limpieza será razonablemente rápida. Lo cual es importante para nuestra aplicación con recursos limitados. –

2

Future.cancel(boolean mayInterruptIfRunning)

intentos para cancelar la ejecución de esta tarea. Este intento fallará si la tarea ya se ha completado, ya se ha cancelado o no se puede cancelar por algún otro motivo. Si tiene éxito, y esta tarea no ha comenzado cuando se invoca cancelar, esta tarea nunca debería ejecutarse. Si la tarea ya ha comenzado, el parámetro mayInterruptIfRunning determina si el hilo que ejecuta esta tarea debe interrumpirse para intentar detener la tarea.

O también se puede utilizar ScheduledThreadPoolExecutor#shutdownNow

Los intentos de detener todas las tareas que ejecutan de forma activa, detiene el procesamiento de tareas en espera, y devuelve una lista de las tareas que se espera de su ejecución.

No hay garantías más allá de los intentos de mejor esfuerzo para detener el procesamiento de tareas de ejecución activa. Esta implementación cancela las tareas a través de Thread.interrupt(), por lo que cualquier tarea que no responda a las interrupciones puede que nunca termine.

Así que debe manejar InterruptedException para permitir la salida segura de los hilos que se están cancelando.

Cuestiones relacionadas