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

javascheduled-tasksspring

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 ?

Best Solution

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.