2011-06-27 10 views
20

Para la ejecución de las tareas periódicas, miré a Timer y ScheduledThreadPoolExecutor (con un solo hilo) y decidió utilizar este último, porque en el reference for Executors.newSingleThreadScheduledExecutor(), que dice:¿Por qué un ScheduledExecutorService no ejecuta una tarea nuevamente después de lanzar una excepción?

Nota sin embargo que si esta solo hilo termina debido a una falla durante la ejecución antes del cierre, una nueva tomará su lugar si es necesario para ejecutar tareas posteriores.

Mi plan era utilizar esto como una protección contra excepciones no detectadas en un código de código de vigilancia que quiero controlar otras operaciones. Quería asegurarme y escribí la prueba a continuación, que falló rápidamente. Parece que estaba haciendo suposiciones equivocadas, ¿o algo está mal en mi prueba?

Aquí está el código:

@Test 
public void testTimer() { 
    final AtomicInteger cTries = new AtomicInteger(0); 
    final AtomicInteger cSuccesses = new AtomicInteger(0); 

    TimerTask task = new TimerTask() { 
     @Override 
     public void run() 
     { 
      cTries.incrementAndGet(); 
      if (true) { 
       throw new RuntimeException(); 
      } 
      cSuccesses.incrementAndGet(); 
     } 
    }; 

    /* 
    Timer t = new Timer(); 
    t.scheduleAtFixedRate(task, 0, 500); 
    */ 
    ScheduledExecutorService exe = Executors.newSingleThreadScheduledExecutor(); 
    exe.scheduleAtFixedRate(task, 0, 500, TimeUnit.MILLISECONDS); 
    synchronized (this) { 
     try { 
      wait(3000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 
    } 
    exe.shutdown(); 
    /* 
    t.purge(); 
    */ 
    Assert.assertEquals(cSuccesses.get(), 0); 
    Assert.assertTrue(cTries.get() > 1, String.format("%d is not greater than 1. :(", cTries.get())); 
} 
+0

Lo sé, puedo envolver una trampa (Throwable) alrededor de cosas, pero mi plan era de alguna manera protegerme de mí mismo. –

+5

sería problemático que un código de marco como este suponga que puede reiniciar de manera segura un trabajo fallido; el hecho de que fallara con una excepción significa que los datos podrían haberse quedado en cualquier tipo de estado y, potencialmente, no sería seguro reiniciarlo el trabajo. –

+3

La cita acerca de cómo iniciar un nuevo hilo es permitir que otros trabajos continúen ejecutándose, incluso si uno falla –

Respuesta

22

Una vez que una tarea que se repite ha lanzado una excepción no capturada se supone que han muerto o estar en un estado de error. Es un poco impreciso que también falla en silencio a menos que examine el futuro para obtener el error/excepción.

Tiene que capturar excepciones si no quiere matar la tarea repetitiva.


como Matt b señala en el comentario anterior,

sería problemático para el código marco como este para asumir que se puede reiniciar de forma segura un trabajo fallido - el hecho de que ha fallado con una excepción significa que los datos pueden haberse quedado en cualquier tipo de estado y, potencialmente, no sería seguro reiniciar el trabajo.

+0

¿Sigue siendo aplicable? En Spring boot 1.5.3, el controlador de error predeterminado para repetir tareas es [LOG_AND_SUPRESS_ERROR_HANDLER] (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/TaskUtils.html# LOG_AND_SUPPRESS_ERROR_HANDLER) que no eliminará @Scheduled de la cola de ejecución. –

+0

Acepto que es una mala idea programar el código para ignorar las excepciones y reiniciar automáticamente, pero ¿puedo programar un servicio RESTful que pueda usar para reiniciar el programador una vez que soluciono el problema de forma manual? – jDub9

+0

@ jDub9 puedes. No hay problema creando un nuevo ExecutorService o una nueva tarea cuando esté listo para ejecutar nuevamente. –

5

matt b ha dado el motivo.

sería problemático para el código marco como éste asuma que puede reiniciar de forma segura un trabajo fallido - el hecho de que ha fallado con una excepción significa que los datos podrían haber sido dejados en cualquier tipo de estado, y potencialmente sería inseguro reiniciar el trabajo.



Cabe señalar que está escrito en la documentación de ScheduledExecutorService

Si cualquier ejecución de la tarea encuentra una excepción, posteriores ejecuciones se suprimen.

Y como dice Michael Krusse, el punto sobre la creación de un nuevo hilo es permitir a otras tareas continúan funcionando.

Cuestiones relacionadas