Search code examples
javaspringconcurrencycronscheduled-tasks

Java Spring: how to run two different cronjobs simultaneously?


First of all, sorry if this has been asked before, I couldn't find a similar question so I decided to ask it myself.

Let's say I have two different cron jobs like this:

@Scheduled(cron = "0 30 * * * *")
private void sleepForDays() {
    while(true) sleep();
}

@Scheduled(cron= "0 * * * * *")
private void logHello() {
   log("hello!");
}

I have a function that runs for days, which is triggered every 30th minute of hour. (0 30 * * * *) Let's name it sleepForDays().

I have another function that is supposed to log hello each minute. Lets name it logHello().

Questions:

  1. Once sleepForDays() is started, I believe second sleepForDays() won't start until first one is finished. Right?

  2. Once sleepForDays() is started, logHello() is not working each minute. I do logging inside this function on my production environment, and I can't see those logs on output file. Clearly it's not working while sleepForDays() is in execution.

Intentions:

  1. I want different cronJobs to operate independently from each other. In other words, I don't want sleepForDays() to block logHello().

  2. I also want to avoid duplicate execution of same cronJob. If sleepForDays() is already executing, I don't want a second sleepForDays() to start.

My main point of posting this question is Question #2. Regarding similar posts in StackOverflow, I believe Question #1's answer is yes. I wanted to make sure my assumption in Question #1 is correct.

Thank you for your time!

Edit:

The problem is probably about the fact that I initialize TaskScheduler bean with default parameters. By default, TaskScheduler do not support multithreading for scheduled cronjobs. If I initialize TaskScheduled bean with multithreading support, will my question #1's answer still be yes?

Bean initialization is as follows:

@Bean
public static TaskScheduler taskScheduler() {
    return new ConcurrentTaskScheduler();
}

Edit 2: Solution

Big thanks to contributors, I managed to run those functions concurrently, using the bean initialization below. I simply replaced TaskScheduler bean with this one:

@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
    ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    threadPoolTaskScheduler.setPoolSize(2);
    threadPoolTaskScheduler.setThreadNamePrefix("ThreadPoolTaskScheduler"); // i dont know what it does, i used it anyways lol
    return threadPoolTaskScheduler;
}

Solution

  • All @Scheduled methods share, by default, a single thread. You can modify this behavior by defining, for example, a custom ThreadPoolTaskScheduler bean:

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(5);
        threadPoolTaskScheduler.setThreadNamePrefix("ThreadPoolTaskScheduler");
        return threadPoolTaskScheduler;
    }