Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop a scheduled task that was started using @Scheduled annotation?

I have created a simple scheduled task using Spring Framework's @Scheduled annotation.

 @Scheduled(fixedRate = 2000)  public void doSomething() {} 

Now I want to stop this task, when no longer needed.

I know there could be one alternative to check one conditional flag at the start of this method, but this will not stop execution of this method.

Is there anything Spring provides to stop @Scheduled task ?

like image 955
Sachin Gupta Avatar asked Jun 20 '17 04:06

Sachin Gupta


People also ask

How do I stop a scheduled task in spring boot?

Canceling the Scheduled Future. Another way to stop the scheduler would be manually canceling its Future. In the cases with multiple scheduler tasks, then we can maintain the Future map inside of the custom scheduler pool but cancel the corresponding scheduled Future based on scheduler class.

How do you stop a scheduler in Java?

The cancel() method is used to cancel the timer task. The cancel() methods returns true when the task is scheduled for one-time execution and has not executed until now and returns false when the task was scheduled for one-time execution and has been executed already.


2 Answers

Option 1: Using a post processor

Supply ScheduledAnnotationBeanPostProcessor and explicitly invoke postProcessBeforeDestruction(Object bean, String beanName), for the bean whose scheduling should be stopped.


Option 2: Maintaining a map of target beans to its Future

private final Map<Object, ScheduledFuture<?>> scheduledTasks =         new IdentityHashMap<>();  @Scheduled(fixedRate = 2000) public void fixedRateJob() {     System.out.println("Something to be done every 2 secs"); }  @Bean public TaskScheduler poolScheduler() {     return new CustomTaskScheduler(); }  class CustomTaskScheduler extends ThreadPoolTaskScheduler {      @Override     public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {         ScheduledFuture<?> future = super.scheduleAtFixedRate(task, period);          ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;         scheduledTasks.put(runnable.getTarget(), future);          return future;     }      @Override     public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {         ScheduledFuture<?> future = super.scheduleAtFixedRate(task, startTime, period);          ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;         scheduledTasks.put(runnable.getTarget(), future);          return future;     } } 

When the scheduling for a bean has to be stopped, you can lookup the map to get the corresponding Future to it and explicitly cancel it.

like image 140
Mahesh Avatar answered Sep 24 '22 00:09

Mahesh


Here is an example where we can stop , start , and list also all the scheduled running tasks:

@RestController @RequestMapping("/test") public class TestController {  private static final String SCHEDULED_TASKS = "scheduledTasks";  @Autowired private ScheduledAnnotationBeanPostProcessor postProcessor;  @Autowired private ScheduledTasks scheduledTasks;  @Autowired private ObjectMapper objectMapper;  @GetMapping(value = "/stopScheduler") public String stopSchedule(){     postProcessor.postProcessBeforeDestruction(scheduledTasks, SCHEDULED_TASKS);     return "OK"; }  @GetMapping(value = "/startScheduler") public String startSchedule(){     postProcessor.postProcessAfterInitialization(scheduledTasks, SCHEDULED_TASKS);     return "OK"; }  @GetMapping(value = "/listScheduler") public String listSchedules() throws JsonProcessingException{     Set<ScheduledTask> setTasks = postProcessor.getScheduledTasks();     if(!setTasks.isEmpty()){         return objectMapper.writeValueAsString(setTasks);     }else{         return "No running tasks !";     }  } } 
like image 43
TinyOS Avatar answered Sep 24 '22 00:09

TinyOS