Understanding SpringBoot @EnableScheduling Issues and Solutions with Thread Pools and Distributed Locks
This article explains how SpringBoot's default @EnableScheduling and @Scheduled annotations can cause execution delays and single‑threaded bottlenecks, demonstrates the root causes in the auto‑configured ThreadPoolTaskScheduler, and provides four practical solutions—including custom thread‑pool configuration, async execution, and Redisson‑based distributed locking—to achieve reliable, concurrent scheduled tasks in both monolithic and distributed environments.
The article begins by introducing the problem of delayed execution and single‑threaded behavior when using SpringBoot's @EnableScheduling and @Scheduled annotations for periodic tasks.
It explains that the auto‑configuration class TaskSchedulingAutoConfiguration creates a ThreadPoolTaskScheduler with a default pool size of 1, which leads to tasks being queued and executed sequentially, especially when a task blocks for a long time (e.g., Thread.sleep(10000)).
Four remediation approaches are presented:
1. Modify configuration properties
spring:
task:
scheduling:
thread-name-prefix: nzc-schedule-
pool:
size: 10Increasing the core pool size allows multiple threads to run concurrently, as shown by the logged thread IDs.
2. Execute logic asynchronously with a custom thread pool
@Configuration
public class MyThreadPoolConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("nzc-create-scheduling-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}The scheduled method injects this executor and runs the job via CompletableFuture.runAsync(..., taskExecutor), resulting in parallel executions.
3. Use @Async with a dedicated executor
@EnableAsync
@EnableScheduling
public class ScheduleService {
@Autowired TaskExecutor taskExecutor;
@Async("taskExecutor")
@Scheduled(cron = "0/5 * * * * ? ")
public void testSchedule() {
Thread.sleep(10000);
log.info("Current thread ID => {}", Thread.currentThread().getId());
}
}This approach also yields separate threads for each execution.
4. Apply a distributed lock (Redisson) for multi‑node safety
@Configuration
public class MyRedissonConfig {
@Bean(destroyMethod="shutdown")
public RedissonClient redissonClient() throws IOException {
Config config = new Config();
config.useSingleServer().setAddress("redis://xxxxx:6379").setPassword("000415");
return Redisson.create(config);
}
} @EnableAsync
@EnableScheduling
public class ScheduleService {
@Autowired TaskExecutor taskExecutor;
@Autowired RedissonClient redissonClient;
private final String SCHEDULE_LOCK = "schedule:lock";
@Async("taskExecutor")
@Scheduled(cron = "0/5 * * * * ? ")
public void testSchedule() {
RLock lock = redissonClient.getLock(SCHEDULE_LOCK);
try {
lock.lock(10, TimeUnit.SECONDS);
Thread.sleep(10000);
log.info("Current thread ID => {}", Thread.currentThread().getId());
} finally {
lock.unlock();
}
}
}The lock ensures that only one instance across a cluster runs the job, preventing duplicate processing and data inconsistency.
Finally, the article notes that while these techniques work for simple monolithic projects, production systems often adopt dedicated distributed scheduling frameworks (e.g., XXL‑JOB) for more robust handling.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
