一、定时任务怎么用?
1️⃣ 开启定时任务
java
@SpringBootApplication
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2️⃣ 编写定时任务
java
@Component
public class OrderTask {
// 每 5 秒执行一次
@Scheduled(fixedRate = 5000)
public void checkOrderStatus() {
System.out.println("检查订单状态...");
}
}
3️⃣ 常见调度方式
java
// 固定间隔(上一次开始 → 下一次开始)
@Scheduled(fixedRate = 5000)
// 固定延迟(上一次结束 → 下一次开始)
@Scheduled(fixedDelay = 5000)
// Cron 表达式(最灵活)
@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨 2 点
4️⃣ Cron 表达式速记
java
秒 分 时 日 月 周
0 0 2 * * ?
-
*任意 -
?不指定 -
0/5每 5 秒 -
MON-FRI周一到周五
📌 适合场景 :
库存检查、数据同步、日志清理、缓存预热
二、线程池
默认的
@Scheduled是单线程的,任务一堵,后面的都排队 🐌。
1️⃣ 自定义线程池
java
@Configuration
@EnableScheduling
public class ScheduleConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
scheduler.setThreadNamePrefix("schedule-");
scheduler.initialize();
return scheduler;
}
}
2️⃣ 好处
-
多任务并行执行
-
不怕某个任务"赖着不走"
四、分布式定时任务:防止"多实例同时跑"
在集群环境中,一个定时任务 可能被多个节点同时执行,很危险 ⚠️。
常见解决方案
✅ 1️⃣ Redis 分布式锁
java
@Scheduled(cron = "0 */5 * * * ?")
public void task() {
if (redisLock.tryLock("order_task")) {
try {
// 业务逻辑
} finally {
redisLock.unlock("order_task");
}
}
}
✅ 2️⃣ ShedLock(强烈推荐)
java
@Scheduled(cron = "0 0 1 * * ?")
@SchedulerLock(name = "cleanTask", lockAtMostFor = "10m")
public void cleanData() {
// 只会有一个实例执行
}