Search code examples
javaspringscheduled-tasksscheduling

Binding two different TaskSchedulers to a Spring Boot Application


I have the following problem: I have multiple @Scheduled annotations in my application defining cron-jobs, which may run at the same time. As far as I understood the standard behavior is that each cron-job is executed by one single-threaded TaskScheduler, so that only one cron-job can run at a time and all other jobs are queued. This would be my desired behavior, but what I experience is that the jobs run in parallel.

After a lot of searching I found out that a class underlying a healthcheck defined a TaskScheduler with multiple threads.

Knowing this, I would like to keep the healthcheck lib using its multithreaded TaskScheduler and define another TaskScheduler, which is single-threaded and used by my @Scheduled annotation.

I can define a Bean which uses a single-threaded scheduler:

@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
  ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
  threadPoolTaskScheduler.setPoolSize(THREADS_COUNT);
  return threadPoolTaskScheduler;
}      

But how is it possible to bind this scheduler to my @Scheduled annotations only?


Solution

  • One could simply let the methods, which are annotated with @Scheduled, call methods, which are annotated with @Async("singleThreadScheduledExecutor"). The "multipleThreadScheduledExecutor" can run in parallel to the async methods and the async methods are queued in a LinkedBlockingQueue when the belonging cron jobs overlap in time. Two other things are important to make it work:

    1. self-invocation – calling the async method from within the same class – won't work
    2. the async methods need to be public

    This is nessecary so spring can build a proxy around the methods.