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 @EnableScheduling on the main class
  • Use @Scheduled on any @Component method to run it automatically
  • fixedRate runs at a fixed interval from the start; fixedDelay waits after each run ends
  • Cron expressions give precise control over execution time
  • Configure a thread pool to allow multiple scheduled tasks to run simultaneously

Leave a Comment

Your email address will not be published. Required fields are marked *