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; } }
We can choose to delay the first execution of the method by specifying the interval using the initialDelay attribute. We can deploy multiple Scheduler Instances using the ShedLock library which ensures only one instance to run at a time by using a locking mechanism in a shared database.
There is no need to use @Async. Just use fixedRate attribute of @Scheduled instead of fixedDelay. Spring will make another invocation on the method after the given time regardless of any call is already being processed.
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
Alternatively, you can configure this property in your application.properties:
spring.task.scheduling.pool.size=2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With