Spring Scheduling with Custom Thread pool
Spring’s @Scheduled allows to execute a function asynchronously as per a given frequency. In this post, we will uncover some common ways to use @Scheduled annotation.
Let’s start with simple example
Output for above
2020-11-06 11:34:18,582 INFO scheduling-1 : Running run1..
2020-11-06 11:34:39,587 INFO scheduling-1 : Running run1..
2020-11-06 11:35:00,595 INFO scheduling-1 : Running run1..
2020-11-06 11:35:21,589 INFO scheduling-1 : Running run1..
2020-11-06 11:35:42,585 INFO scheduling-1 : Running run1..
2020-11-06 11:36:03,584 INFO scheduling-1 : Running run1..
There are two important things to note in the output
- Notice the frequency of logs. The logs are being printed with delay of 20 seconds whereas the @Scheduled frequency is set to 1 second. Second execution is blocked until first execution completes.
- Only one thread is being used to execute the scheduled method.
By default, Spring @Scheduled annotation uses default thread pool of size 1 and executions of scheduled method happen synchronously in respect to other executions of method.
For very short running tasks, having single thread can suffice. However, in real world use cases, your function may take longer depending upon the processing done and dependencies on external systems such as a database.
So, let us improve this and get multi-threaded.
@Scheduled with custom thread pool
Let’s create a bean to define our own Thread pool using Java Executor Service
Let’s run the SimpleScheduledExample again. Below is the output now
2020-11-06 11:54:35,222 INFO pool-2-thread-2 : Running run1..
2020-11-06 11:54:56,225 INFO pool-2-thread-3 : Running run1..
2020-11-06 11:55:17,230 INFO pool-2-thread-2 : Running run1..
2020-11-06 11:55:38,235 INFO pool-2-thread-4 : Running run1..
2020-11-06 11:55:59,244 INFO pool-2-thread-3 : Running run1..
Lets analyse the output again
- Executions of method are now performed in separate threads. (yay!)
- Wait a minute, the executions are still blocking :( Logs are getting printed with delay of 20 seconds.
Spring’s @Scheduled annotation by default blocks further execution until current execution is complete.
Hmmmm, using custom thread pool is better but ideally we want the executions to be asynchronous.
Spring’s @Async to the rescue
@Async annotation from Spring can be used on a method to execute it asynchronously.
To enable @Async, add @EnableAsync on your Spring boot configuration.
Here is the updated code
Let’s run it. Below is the output
2020-11-06 12:01:58,039 INFO pool-2-thread-7 : Running run1..
2020-11-06 12:01:59,041 INFO pool-2-thread-1 : Running run1..
2020-11-06 12:02:00,047 INFO pool-2-thread-6 : Running run1..
2020-11-06 12:02:01,053 INFO pool-2-thread-12 : Running run1..
2020-11-06 12:02:02,056 INFO pool-2-thread-5 : Running run1..
2020-11-06 12:02:03,057 INFO pool-2-thread-15 : Running run1..
2020-11-06 12:02:04,061 INFO pool-2-thread-14 : Running run1..
2020-11-06 12:02:05,063 INFO pool-2-thread-10 : Running run1..
Now, the method invocations are running with a fixed delay of 1 second and executions are non-blocking .
Hope this was useful. Happy Reading !!