2

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?

  • It seems this is not possible with the `@Scheduled` annotation: https://github.com/spring-projects/spring-framework/issues/18792. You could define your tasks in Java Config and scheduled them on the correct `TaskScheduler` yourself. – marcok Aug 13 '19 at 11:52

1 Answers1

0

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.