SpringBoot 定时调度与异步执行机制详解
启用定时调度功能
要在 SpringBoot 应用中开启定时任务支持,需在主入口类添加 @EnableScheduling 注解:
@SpringBootApplication
@EnableScheduling
public class ScheduleApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleApplication.class, args);
}
}
定义定时任务
创建任务类并使用 @Component 将其纳入容器管理,通过 @Scheduled 配置执行规则:
@Component
public class DataSyncJob {
// 使用 Cron 表达式,每秒触发
@Scheduled(cron = "0/1 * * * * ?")
public void syncTask() {
System.out.println("数据同步开始: " + LocalDateTime.now());
}
// 固定间隔模式,上次结束后延迟2秒
@Scheduled(fixedDelay = 2000)
public void cleanupTask() {
System.out.println("清理任务执行: " + LocalDateTime.now());
}
// 固定频率模式,每2秒触发一次(无论上次是否完成)
@Scheduled(fixedRate = 2000)
public void reportTask() {
System.out.println("报表生成: " + LocalDateTime.now());
}
}
Cron 表达式语法
Cron 表达式由6个必填字段组成(第7位年份可省略):
| 位置 | 含义 | 取值范围 |
|---|---|---|
| 第1位 | 秒 | 0-59 |
| 第2位 | 分 | 0-59 |
| 第3位 | 时 | 0-23 |
| 第4位 | 日 | 1-31 |
| 第5位 | 月 | 1-12 |
| 第6位 | 周 | 1-7(1=周日) |
常用表达式示例
0/30 * * * * * // 每30秒执行
0 0/5 * * * * // 每5分钟执行
0 0 2 * * ? // 每日凌晨2点
0 0 9,14,18 * * ? // 每天9点、14点、18点
0 30 1-3 * * ? // 每天1至3点的30分执行
特殊符号说明
*:匹配任意值,表示"每"?:仅用于日或周字段,表示不指定(两者互斥,需用其一)-:定义范围,如10-12表示10点到12点,:枚举多个值,如MON,WED,FRI/:指定步长,如0/15从0开始每15秒
@Scheduled 参数对比
| 参数 | 说明 |
|---|---|
fixedRate | 以固定频率触发,从上一次开始计时 |
fixedDelay | 从上一次结束后延迟指定时间 |
initialDelay | 首次执行前的延迟时间,需配合上述两者使用 |
cron | 基于 Cron 表达式的灵活调度 |
启用异步执行
在主类添加 @EnableAsync 注解激活异步支持:
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class AsyncApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncApplication.class, args);
}
}
异步方法实现
使用 @Async 标记需要异步执行的方法:
@Service
public class OrderService {
@Async
public CompletableFuture<String> processPayment(Long orderId) {
// 模拟耗时操作
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("支付处理完成: " + orderId);
return CompletableFuture.completedFuture("SUCCESS");
}
}
调用异步服务
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/create")
public String createOrder() {
System.out.println("步骤1: 接收请求 " + System.currentTimeMillis());
// 异步调用,立即返回
orderService.processPayment(10086L);
System.out.println("步骤2: 响应客户端 " + System.currentTimeMillis());
return "订单创建成功";
}
}
同步 vs 异步执行效果
未启用 @Async 时(同步):
步骤1: 接收请求 1699123456789
支付处理完成: 10086
步骤2: 响应客户端 1699123459792 // 等待3秒后输出
启用 @Async 后(异步):
步骤1: 接收请求 1699123456789
步骤2: 响应客户端 1699123456790 // 立即输出
支付处理完成: 10086 // 3秒后后台输出
线程池配置(可选)
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Override
@Bean(name = "taskExecutor")
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-");
executor.initialize();
return executor;
}
}