1. Overview
In this article, we’ll discuss the Spring task scheduling mechanisms – TaskScheduler and it’s pre-built implementations along with the different triggers to use. If you want to read more about scheduling in Spring, check @Async and @Scheduled articles.
TaskScheuler was introduced in Spring 3.0 with a variety of methods to run at some point in the future, it also returns a representation object of ScheduledFuture interface, which could be used to cancel scheduled task or check if it’s done or not.
All we need to do is to select a runnable task for scheduling then select a proper scheduling policy.
2. ThreadPoolTaskScheduler
ThreadPoolTaskScheduler is well suited for internal thread management, as it delegates tasks to the ScheduledExecutorService and implements the TaskExecutor interface – so that single instance of it is able to handle asynchronous potential executions as well as the @Scheduled annotation.
Let’s now define ThreadPoolTaskScheduler bean at ThreadPoolTaskSchedulerConfig:
@Configuration @ComponentScan( basePackages="org.baeldung.taskscheduler", basePackageClasses={ThreadPoolTaskSchedulerExamples.class}) public class ThreadPoolTaskSchedulerConfig { @Bean public ThreadPoolTaskScheduler threadPoolTaskScheduler(){ ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); threadPoolTaskScheduler.setPoolSize(5); threadPoolTaskScheduler.setThreadNamePrefix( "ThreadPoolTaskScheduler"); return threadPoolTaskScheduler; } }
The configured bean threadPoolTaskScheduler can execute tasks asynchronously based on the configured pool size of 5.
Note that all ThreadPoolTaskScheduler related thread names will be prefixed with ThreadPoolTaskScheduler.
Let’s implement a simple task we can then schedule:
class RunnableTask implements Runnable{ private String message; public RunnableTask(String message){ this.message = message; } @Override public void run() { System.out.println(new Date()+" Runnable Task with "+message +" on thread "+Thread.currentThread().getName()); } }
We can now simple schedule this task to be executed by the scheduler:
taskScheduler.schedule( new Runnabletask("Specific time, 3 Seconds from now"), new Date(System.currentTimeMillis + 3000) );
The taskScheduler will schedule this runnable task at a known date, exactly 3 seconds after the current time.
Let’s now go a bit more in depth with the ThreadPoolTaskScheduler scheduling mechanisms.
3. Schedule Runnable task with Fixed Delay
Scheduling with a fixed delay can be done with two simple mechanisms:
3.1. Scheduling after a Fixed Delay of The Last Scheduled Execution
Let’s configure a task to run after a fixed delay of 1000 milliseconds:
taskScheduler.scheduleWithFixedDelay( new RunnableTask("Fixed 1 second Delay"), 1000);
The RunnableTask will always run 1000 milliseconds later between the completion of one execution and the start of the next.
3.2. Scheduling after a Fixed Delay of a Specific Date
Let’s configure a task to run after a fixed delay of a given start time:
taskScheduler.scheduleWithFixedDelay( new RunnableTask("Current Date Fixed 1 second Delay"), new Date(), 1000);
The RunnableTask will be invoked at the specified execution time which mainly the time in which @PostConstruct method starts and subsequently with 1000 milliseconds delay.
4. Scheduling at a Fixed Rate
There are two simple mechanisms for scheduling runnable tasks at fixed rate:
4.1. Scheduling The RunnableTask at a Fixed Rate
Let’s schedule a task to run at a fixed rate of milliseconds:
taskScheduler.scheduleAtFixedRate( new RunnableTask("Fixed Rate of 2 seconds") , 2000);
The next RunnableTask will run always after 2000 milliseconds no matter the status of last execution which may be still running.
4.2. Scheduling The RunnableTask at a Fixed Rate from a Given Date
taskScheduler.scheduleAtFixedRate(new RunnableTask( "Fixed Rate of 2 seconds"), new Date(), 3000);
The RunnableTask will run 3000 milliseconds after the current time.
5. Scheduling with CronTrigger
CronTrigger is used to schedule a task based on a cron expression:
CronTrigger cronTrigger = new CronTrigger("10 * * * * ?");
The provided trigger can be used to run a task according to a certain specified cadence or schedule:
taskScheduler.schedule(new RunnableTask("Cron Trigger"), cronTrigger);
In this case, the RunnableTask will be executed at the 10th second of every minute.
6. Scheduling with PeriodicTrigger
Let’s use PeriodicTrigger for scheduling a task with a fixed delay of 2000 milliseconds:
PeriodicTrigger periodicTrigger = new PeriodicTrigger(2000, TimeUnit.MICROSECONDS);
The configured PeriodicTrigger bean would be used to run a task after a fixed delay of 2000 millisecond.
Now let’s schedule the RunnableTask with the PeriodicTrigger:
taskScheduler.schedule( new RunnableTask("Periodic Trigger"), periodicTrigger);
We also can configure PeriodicTrigger to be initialized at a fixed rate rather than fixed delay, also we can set an initial delay for the first scheduled task by a given milliseconds.
All we need to do is to add two lines of code before return statement at the periodicTrigger bean:
periodicTrigger.setFixedRate(true); periodicTrigger.setInitialDelay(1000);
We used setFixedRate method to schedule the task at fixed rate rather than with a fixed delay, then setInitialDelay method is used to set initial delay only for the first runnable task to run.
7. Conclusion
In this quick article, we’ve illustrated how to schedule a runnable task using the Spring support for tasks.
We looked at running the task with a fixed delay, at a fixed rate and according to a specified trigger.
And, as always, the code is available as a Maven project over in Github.