早期需在 XML 定義 MethodInvokingJobDetailFactoryBean + CronTriggerFactoryBean + SchedulerFactoryBean,繁瑣易錯。Spring 3.0+ 引入 @Scheduled + @EnableScheduling,大幅簡化。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.3.21</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<beans xmlns:task="https://www.springframework.org/schema/task"
xsi:schemaLocation="https://www.springframework.org/schema/task
https://www.springframework.org/schema/task/spring-task.xsd">
<!-- 線程池調度器 -->
<task:scheduler id="taskScheduler" pool-size="10"/>
<!-- 啟用 @Scheduled 掃描 -->
<task:annotation-driven scheduler="taskScheduler"/>
</beans>
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar registrar) {
registrar.setTaskScheduler(new ThreadPoolTaskScheduler() {{
setPoolSize(10);
setThreadNamePrefix("scheduled-");
initialize();
}});
}
}
@Component
public class OrderTimeoutTask {
private static final DateTimeFormatter FMT =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Scheduled(cron = "0/10 * * * * ?") // 每 10 秒
public void checkTimeoutOrders() {
try {
TimeUnit.SECONDS.sleep(20); // 模擬耗時邏輯
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
log.info("{} ********* 定時任務執行", LocalDateTime.now().format(FMT));
}
}
秒 分 時 日 月 周 [年]
* * * * * ? 每秒
0 0 12 * * ? 每天中午 12:00
0 15 10 ? * MON-FRI 工作日 10:15
0 0 0 1 * ? 每月 1 號 00:00
0 0 0 ? * 6#3 每月第三個周六
現象:任務執行時間 > 間隔時間 → 線程池佔滿、數據重複處理
pool-size 並配置 @Async 異步執行@Component
public class DynamicTaskManager {
@Resource private ThreadPoolTaskScheduler scheduler;
private final Map> futures = new ConcurrentHashMap<>();
public void addTask(String name, Runnable task, String cron) {
CronTrigger trigger = new CronTrigger(cron);
ScheduledFuture> future = scheduler.schedule(task, trigger);
futures.put(name, future);
}
public void removeTask(String name) {
ScheduledFuture> f = futures.remove(name);
if (f != null) f.cancel(true);
}
}
/actuator/scheduledtasks 查看下次執行時間、執行統計logging.level.org.springframework.scheduling=DEBUGcron="0/10 * * * * ?" 缺少秒位會報錯,Spring Cron 6 位必須以秒開頭