DEV Community

Avinay Basnet
Avinay Basnet

Posted on • Edited on

Programmatically Scheduling and Cancelling Task with Spring Boot

Spring offers @Scheduled annotation to configure and schedule tasks. Methods annotated with @Scheduled are automatically scheduled. If you are not familiar with this read the following article by Eugen.

https://www.baeldung.com/spring-scheduled-tasks

We will be leveraging Spring's ThreadPoolTaskScheduler to implement our custom task scheduler which we can programmatically trigger.

The ThreadPoolTaskScheduler helps manage threads internally by assigning tasks to the ScheduledExecutorService and implements TaskExecutor interface. With just one instance, it can handle tasks that might run asynchronously, including those marked with the @Scheduled annotation.

public class CustomTaskScheduler extends ThreadPoolTaskScheduler {

    private final Map<String, ScheduledFuture<?>> scheduledTasks = new IdentityHashMap<>();

    public void scheduleAtFixedRate(Runnable task, Duration period, String id) {
        ScheduledFuture<?> future = super.scheduleAtFixedRate(task, period);
        scheduledTasks.put(id, future);
    }
}
Enter fullscreen mode Exit fullscreen mode

Just like @Scheduled(fixedRate = 1000), super.scheduleAtFixedRate(task, period) we have provided a fixed Duration. We will later implement our Runnable task.

super.scheduleAtFixedRate(task, period) returns a ScheduledFuture which is basically a delayed result that can be cancelled at any time. So to get hold of it later we are keeping ScheduledFuture in scheduledTasks.

Let's see how we can cancel the ScheduledFuture.

public void cancelScheduledTask(String id) {
        ScheduledFuture<?> future = scheduledTasks.get(id);
        if (null != future) {
            future.cancel(true);
        }
    }
Enter fullscreen mode Exit fullscreen mode

If the task has not started when cancel is called, the task will never run. If the task has already started, then the future.cancel(true) accepts a boolean parameter, mayInterruptIfRunning, which determines whether the thread executing this task is interrupted in an attempt to stop the task. Passing true means interrupted the task if needed.

Now, let's implement task which we need to schedule.

public class RunnableTask implements Runnable {

    private String id;

    public RunnableTask() {
    }

    public RunnableTask(String id) {
        this.id = id;
    }

    @Override
    public void run() {
        // perform task here
    }
}
Enter fullscreen mode Exit fullscreen mode

An example to schedule task:

String id = UUID.randomUUID().toString();
RunnableTask task = new RunnableTask(id);
customTaskScheduler.scheduleAtFixedRate(task,Duration.ofMinutes(1, id);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)