2011-01-27 8 views
11

Tengo un ExecutorService que gestiona una cantidad de Callables. Las tareas que ejecutan los Callables son en su mayoría transformaciones de caja negra y procesamiento de números. Bajo ciertas condiciones, los datos que se están transformando oscilarán y el hilo tardará más de una hora en finalizar. Para comparar, la mayoría de los hilos se completan en un minuto.Límite de tiempo en hilos individuales con ExecutorService

Se ha detectado que los datos de los hilos de ejecución prolongada no son relevantes. Me gustaría interrumpir cualquier hilo que se ejecute más de una cierta cantidad de tiempo. ¿Cuál sería la mejor manera de hacer esto?

Respuesta

19

Utilice un ScheduleExecutorService para programar una tarea en taskFuture.cancel(true) la tarea de larga ejecución cuando se alcanza el tiempo de espera. Si la tarea finaliza antes, no se cancelará.

ExecutorService service = Executors.newFixedThreadPool(N); 
ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor(); 

public <T> Future<T> executeTask(Callable<T> c, long timeoutMS){ 
    final Future<T> future = service.submit(c); 
    canceller.schedule(new Callable<Void>(){ 
     public Void call(){ 
      future.cancel(true); 
      return null; 
     } 
    }, timeoutMS, TimeUnit.MILLI_SECONDS); 
    return future; 
} 
3

La mejor manera de hacerlo sería introducir un ejecutor más. Puede utilizar un ScheduledExecutorService para cancelar todas las tareas de ejecución larga, por ejemplo:

ExecutorService service = Executors.newFixedThreadPool(N); 

ScheduledExecutorService canceller = Executors.newScheduledThreadPool(1); 

public void executeTask(Callable<?> c){ 
    final Future<?> future = service.submit(c); 
    canceller.schedule(new Runnable(){ 
     public void run(){ 
      future.cancel(true); 
     } 
    }, SECONDS_UNTIL_TIMEOUT, TimeUnit.SECONDS); 
} 
+0

La llamada debe devolver un valor. –

+1

Gracias, puedes imaginar que acabo de escribir eso con las manos libres. Si solo Firefox tenía un compilador incorporado :) –

0

Se puede obtener una lista de sus futuros correspondientes (que se crean cuando se envía una opción de rescate) junto con su tiempo de inicio.

Otra tarea podría comprobar cada minuto si hay alguna tarea ejecutándose durante más de un tiempo definido y, si es así, invocar cancelar (verdadero) en el futuro. Los futuros listos se eliminarán de la lista.

0

Puede utilizar este método

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, 
           long timeout, 
           TimeUnit unit) 
          throws InterruptedException 

y establecer el tiempo de espera máximo de un minuto. Si su hilo toma más que eso, simplemente se cancela.

5

Puede cancelar el futuro, etc. como en las otras respuestas, pero debe asegurarse de que sus hilos que son "números crujientes" pueden manejar la interrupción y terminar graciosamente. Usted dice que se trata de una operación de caja negra: ¿qué tan seguro está de que el estado interrumpido del hilo se compruebe activamente dentro de la caja negra? Si no es así, no puede cancelarlo con una interrupción. La caja negra debe escribirse con la interrupción en mente.

+0

+1 para señalar que la tarea podría requerir algo de inteligencia. – Raedwald

Cuestiones relacionadas