Step 18 of 51
@Scheduled, cron expressions, fixed rates, dynamic scheduling. Distributed scheduling considerations.
Cronjob — งานตั้งเวลาที่ทุก backend ต้องมี
Last verified: June 2026 — ShedLock 5.10.0
Use scheduled tasks for periodic work: daily cleanup, report generation, cache warming, data sync. If it runs on a clock, use @Scheduled.
@Configuration
@EnableScheduling
public class SchedulingConfig {
}
@Component
@RequiredArgsConstructor
@Slf4j
public class ScheduledTasks {
private final CleanupService cleanupService;
private final ReportService reportService;
private final CacheService cacheService;
@Scheduled(cron = "0 0 2 * * *")
public void nightlyCleanup() {
log.info("Starting nightly cleanup");
cleanupService.removeExpiredSessions();
cleanupService.archiveOldOrders();
}
@Scheduled(fixedRate = 30_000)
public void refreshCache() {
cacheService.warmProductCache();
}
@Scheduled(fixedDelay = 60_000)
public void syncExternalData() {
reportService.syncFromExternalApi();
}
@Scheduled(cron = "0 0 9 * * MON-FRI")
public void weekdayReport() {
reportService.generateDailySummary();
}
}
| Annotation | Meaning |
|---|---|
cron = "0 0 2 * * *" | Every day at 2:00 AM |
fixedRate = 30_000 | Every 30 seconds from start to start |
fixedDelay = 60_000 | 60 seconds after the previous run finishes |
fixedRate starts the next run regardless of whether the previous finished. fixedDelay waits for the previous run to complete.
┌─────────── second (0-59)
│ ┌───────── minute (0-59)
│ │ ┌─────── hour (0-23)
│ │ │ ┌───── day of month (1-31)
│ │ │ │ ┌─── month (1-12)
│ │ │ │ │ ┌─ day of week (0-7, 0 and 7 = Sunday)
│ │ │ │ │ │
0 0 2 * * *
Common patterns:
0 0 * * * * — every hour0 */15 * * * * — every 15 minutes0 0 9 * * MON-FRI — weekdays at 9 AM0 0 0 1 * * — first day of every monthWhen running multiple instances, every instance runs the scheduled task. You need a distributed lock.
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>5.10.0</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>5.10.0</version>
</dependency>
@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "10m")
public class SchedulingConfig {
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(dataSource);
}
}
@Component
@RequiredArgsConstructor
public class DistributedScheduledTasks {
private final ReportService reportService;
@Scheduled(cron = "0 0 2 * * *")
@SchedulerLock(name = "nightlyReport",
lockAtLeastFor = "PT5M",
lockAtMostFor = "PT30M")
public void nightlyReport() {
reportService.generateDailySummary();
}
}
Only one instance acquires the lock and runs the task. lockAtLeastFor prevents another instance from running it too soon. lockAtMostFor is a safety net — if the instance crashes, the lock releases after 30 minutes.
@Component
@RequiredArgsConstructor
public class DynamicScheduler {
private final TaskScheduler taskScheduler;
private ScheduledFuture<?> currentTask;
public void schedule(Runnable task, String cronExpression) {
if (currentTask != null) {
currentTask.cancel(false);
}
currentTask = taskScheduler.schedule(task,
new CronTrigger(cronExpression));
}
}
fixedDelay for tasks that should not overlap; fixedRate for independent periodic checks