java - mediante - Tarea de programación de Spring-ejecutar solo una vez
spring framework pdf español (3)
Para no crear ScheduledExecutorService
y ConcurrentTaskScheduler
en cada llamada de método, es conveniente inicializar TaskScheduler
en la creación del servicio, por ejemplo
private final TaskScheduler taskScheduler =
new ConcurrentTaskScheduler(Executors.newScheduledThreadPool(10));
@Async
no tiene sentido ya que solo programamos la tarea y salimos del método.
¿Es posible programar el método de servicio Spring solo una vez a la hora exacta especificada? Por ejemplo, la hora actual es 2pm pero cuando presiono el botón de acción quiero que mi método de servicio comience a las 8pm. Estoy familiarizado con la anotación @Scheduled y no estoy seguro de cómo escribir la expresión cron para que no se ejecute periódicamente. Este @Scheduled(cron = "0 0 20 * * ?")
dispara todos los días a las 8pm.
¿Alguna sugerencia?
Puede extender PeriodicTrigger de la siguiente manera: comprueba lastCompletionTime: será nulo si la tarea nunca se ha ejecutado antes. Puede intentar una variación de esto si desea ejecutar la tarea solo una vez en un momento dado.
class RunOnceTrigger extends PeriodicTrigger {
public RunOnceTrigger(long period) {
super(period);
setInitialDelay(period);
}
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
if(triggerContext.lastCompletionTime() == null) { // hasn''t executed yet
return super.nextExecutionTime(triggerContext);
}
return null;
}
}
Puedes usar una de las implementaciones de SpringScheduler. Proporcioné un ejemplo a continuación con uno que no requiere demasiada configuración (ConcurrentTaskScheduler que envuelve un ejecutor programado de un solo hilo).
El método más simple es el programa con un nombre que toma solo una fecha de ejecución y fecha. Eso hará que la tarea se ejecute una vez después del tiempo especificado . Todos los otros métodos son capaces de programar tareas para ejecutar repetidamente.
Lea más sobre la ejecución de tareas y programación
Ejemplo de trabajo simple:
private TaskScheduler scheduler;
Runnable exampleRunnable = new Runnable(){
@Override
public void run() {
System.out.println("Works");
}
};
@Async
public void executeTaskT() {
ScheduledExecutorService localExecutor = Executors.newSingleThreadScheduledExecutor();
scheduler = new ConcurrentTaskScheduler(localExecutor);
scheduler.schedule(exampleRunnable,
new Date(1432152000000L));//today at 8 pm UTC - replace it with any timestamp in miliseconds to text
}
...
executeTaskT() //call it somewhere after the spring application has been configured
Nota :
Para habilitar el soporte para las anotaciones @Scheduled y @Async, agregue @EnableScheduling y @EnableAsync a una de sus clases @Configuration
Actualización - cancelando la tarea programada
El método de programación de TaskScheduler devuelve un ScheduledFuture, que es una acción demorada de resultados que se puede cancelar .
Por lo tanto, para cancelarlo, debe mantener un identificador de la tarea programada (es decir, mantener el objeto devuelto ScheduledFuture).
Cambios en el código anterior para cancelar la tarea:
Declare el ScheduledFuture fuera de su método executeTaskT.
private ScheduledFuture scheduledFuture;
Modifique su llamada para programar para mantener el objeto de retorno como tal:
scheduledFuture = scheduler.schedule(exampleRunnable, new Date(1432152000000L));
Llame a cancel en el objeto scheduleFuture en algún lugar de su código
boolean mayInterruptIfRunning = true; scheduledFuture.cancel(mayInterruptIfRunning);
boolean mayInterruptIfRunning = true; scheduledFuture.cancel(mayInterruptIfRunning);