@Scheduled — executing tasks on a schedule (cron) without an external scheduler.
Simple analogy: @Scheduled is like an alarm clock. You set it to "every 5 minutes" or "every Monday at 9:00" — Spring rings at the right time. Think of it like a weekly cleaning service: you give them a key (enable scheduling) and a schedule ("every Friday at 6 PM"), and they come automatically without you calling each time.
Why it matters: Many applications need periodic background work — cleaning old data, syncing external APIs, sending batch emails, refreshing caches, generating reports. Without scheduled tasks, you would need external tools (cron, Kubernetes CronJobs) or manual triggers.
Enabling:
1@SpringBootApplication2@EnableScheduling3public class MyApp { ... }
Examples:
1@Service2@Slf4j3public class ScheduledTasks {45 @Scheduled(fixedRate = 5000) // Every 5 seconds (from start of previous)6 public void checkHealth() {7 log.info("Health check at {}", LocalDateTime.now());8 }910 @Scheduled(fixedDelay = 10000) // 10 seconds after previous COMPLETION11 public void syncData() {12 log.info("Data sync completed");13 }1415 @Scheduled(cron = "0 0 2 * * ?") // Every day at 2:00 AM16 public void cleanupOldRecords() {17 repository.deleteOlderThan(LocalDate.now().minusYears(1));18 }1920 @Scheduled(cron = "0 */5 * * * *") // Every 5 minutes21 public void refreshCache() {22 cacheManager.getCache("products").clear();23 }2425 @Scheduled(cron = "0 0 9 * * MON-FRI") // Weekdays at 9 AM26 public void sendDailyDigest() {27 emailService.sendDigest();28 }29}
Pool configuration:
1spring:2 task:3 scheduling:4 pool:5 size: 5 # 5 threads for scheduled tasks6 thread-name-prefix: scheduled-task-7 shutdown:8 await-termination: true9 await-termination-period: 30s
Common mistakes:
1@Scheduled(fixedRate = 60000)2public void riskyTask() {3 try {4 doWork();5 } catch (Exception e) {6 log.error("Scheduled task failed", e);7 }8}
fixedRate for long tasks — if the task takes longer than the interval, multiple threads execute it simultaneously. Use fixedDelay instead.For production — Quartz Scheduler:
1@Configuration2public class QuartzConfig {3 @Bean4 public SchedulerFactoryBean schedulerFactoryBean() {5 SchedulerFactoryBean factory = new SchedulerFactoryBean();6 factory.setJobDetails(jobDetail());7 factory.setTriggers(trigger());8 factory.setOverwriteExistingJobs(true);9 return factory;10 }11}
@Scheduled vs Quartz: