Spring Boot Scheduling
Scheduling runs tasks automatically at fixed times or intervals — no external trigger needed. Use it for sending daily email reports, cleaning old database records, or syncing data from an external API every hour.
Enable Scheduling
@SpringBootApplication
@EnableScheduling ← Activates the scheduling infrastructure
public class DemoApplication { ... }
Creating a Scheduled Task
@Component
public class ReportScheduler {
@Scheduled(cron = "0 0 8 * * MON-FRI") ← 8 AM, Monday to Friday
public void sendDailyReport() {
System.out.println("Sending daily report at 8 AM...");
reportService.generateAndSend();
}
@Scheduled(fixedRate = 60000) ← Every 60 seconds
public void syncInventory() {
inventoryService.syncFromWarehouse();
}
}
Three Ways to Schedule
1. Fixed Rate
@Scheduled(fixedRate = 5000) ← Run every 5 seconds
public void heartbeat() { ... }
// Time is measured from the START of the previous execution
// If a run takes 3s, the next run starts 5s after the previous START
2. Fixed Delay
@Scheduled(fixedDelay = 5000) ← Wait 5 seconds after previous run ends
public void processQueue() { ... }
// Time is measured from the END of the previous execution
// Safer when tasks have variable duration
3. Cron Expression
@Scheduled(cron = "seconds minutes hours day-of-month month day-of-week") Examples: "0 0 * * * *" Every hour (at 0 minutes 0 seconds) "0 30 9 * * *" Every day at 9:30 AM "0 0 8 * * MON-FRI" 8 AM on weekdays "0 0 0 1 * *" First day of every month at midnight "0 */15 * * * *" Every 15 minutes
Cron Expression Structure
┌──────────── second (0–59) │ ┌────────── minute (0–59) │ │ ┌──────── hour (0–23) │ │ │ ┌────── day of month (1–31) │ │ │ │ ┌──── month (1–12 or JAN–DEC) │ │ │ │ │ ┌── day of week (0–7 or MON–SUN) │ │ │ │ │ │ 0 30 9 * * MON-FRI
Special Cron Symbols
Symbol Meaning ────── ────────────────────────────────────── * Every possible value , List: MON,WED,FRI - Range: MON-FRI / Step: */15 = every 15 ? No specific value (day fields only)
Using Properties for Schedule Values
Hardcoding schedules makes them hard to change. Move them to properties:
# application.properties app.schedule.report=0 0 8 * * MON-FRI app.schedule.sync=*/30 * * * * *
@Scheduled(cron = "${app.schedule.report}")
public void sendReport() { ... }
@Scheduled(fixedRateString = "${app.schedule.sync}")
public void syncData() { ... }
Adding an Initial Delay
// Wait 10 seconds after startup, then run every 60 seconds
@Scheduled(initialDelay = 10000, fixedRate = 60000)
public void startAfterDelay() { ... }
This prevents tasks from running before the app fully initializes.
Scheduling Thread Behaviour
Default: All @Scheduled tasks share ONE thread
┌──────────────────────────────────────────────────┐
│ Single Scheduler Thread │
│ Task A (10s) → Task B (5s) → Task A (10s) →... │
└──────────────────────────────────────────────────┘
Problem: If Task A runs for 30s, Task B is delayed.
Configure a thread pool to let tasks run in parallel:
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar registrar) {
registrar.setScheduler(Executors.newScheduledThreadPool(5));
// ↑ 5 threads
}
}
Summary
- Enable scheduling with
@EnableSchedulingon the main class - Use
@Scheduledon any@Componentmethod to run it automatically fixedRateruns at a fixed interval from the start;fixedDelaywaits after each run ends- Cron expressions give precise control over execution time
- Configure a thread pool to allow multiple scheduled tasks to run simultaneously
