Multiple Spring @Scheduled tasks simultaneously
Asked Answered
D

2

35

I'm trying to run multiple scheduled tasks at the same time on spring boot, but in practice they run queuing (one after the other, not parallel)

This is my simple service:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class MyScheduleDemo {

    @Scheduled(fixedDelay = 5000, initialDelay = 1000)
    public void taskA() throws InterruptedException {
        System.out.println("[A] Starting new cycle of scheduled task");

        // Simulate an operation that took 5 seconds.
        long startTime = System.currentTimeMillis();
        while (System.currentTimeMillis() - startTime <= 5000);

        System.out.println("[A] Done the cycle of scheduled task");
    }

    @Scheduled(fixedDelay = 5000, initialDelay = 2000)
    public void taskB() throws InterruptedException {
        System.out.println("[B] Starting new cycle of scheduled task");

        System.out.println("[B] Done the cycle of scheduled task");
    }
}

Output:

[A] Starting new cycle of scheduled task
[A] Done the cycle of scheduled task
[B] Starting new cycle of scheduled task
[B] Done the cycle of scheduled task

But, It should be like:

[A] Starting new cycle of scheduled task
[B] Starting new cycle of scheduled task
[B] Done the cycle of scheduled task
[A] Done the cycle of scheduled task

What am I doing wrong?

This is my configuration:

@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    @Bean(name = "taskExecutor")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(6);
        executor.setMaxPoolSize(50);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("customer-Executor-");
        executor.initialize();
        return executor;
    }
}
Dorina answered 6/7, 2017 at 8:49 Comment(2)
You are confusing TaskExecutor with TaskScheduler you haven't configured the latter and thus everything runs in sync mode (the default).Gaby
Thanks @M.Deinum !!Dorina
B
37

You should use TaskScheduler for your purpose

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

Where THREADS_COUNT - total count of tasks which should be executed in parallel. If I understand you correctly, you have only 2 jobs, so you need 2 threads

Bail answered 6/7, 2017 at 10:34 Comment(1)
And keep in mind that every default @Async annotation uses this scheduler, too. If you use @Scheduled and call @Async methods thery aren't executed until a thread is available.Tilly
M
26

Alternatively, you can configure this property in your application.properties:

spring.task.scheduling.pool.size=2
Monolingual answered 9/12, 2021 at 7:44 Comment(1)
Simple and easy fix. Worked like a charm. My context was that I had 5 @Scheduled(fixedDelay=5000) methods. Threads were fighting for priority. Setting the pool size to 5 fixed the issue. Thanks again.Rustproof

© 2022 - 2024 — McMap. All rights reserved.