
一、为什么需要定时与异步?
在后端系统中,常常会遇到以下需求:
- 每天定时清理日志或数据
- 定期发送邮件或短信提醒
- 异步执行耗时任务,避免阻塞主线程
Spring 提供了非常轻量的方式处理这些场景:@Scheduled
和 @Async
。
二、@Scheduled:定时任务注解
Spring Boot 原生支持定时任务,只需:
1. 开启定时任务支持
@SpringBootApplication
@EnableScheduling
public class MyApplication {}
2. 定义定时任务方法
@Component
public class TaskService {
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
System.out.println("每5秒执行一次:" + LocalDateTime.now());
}
@Scheduled(cron = "0 0 3 * * ?")
public void cleanUpData() {
System.out.println("每天凌晨3点执行清理任务");
}
}
三、@Scheduled 常用参数
属性 | 说明 |
---|---|
fixedRate | 上一次开始执行后多长时间再次执行 |
fixedDelay | 上一次执行完成后多长时间执行 |
initialDelay | 初次延迟 |
cron | 使用 cron 表达式进行时间控制 |
示例:
// 每小时整点执行
@Scheduled(cron = "0 0 * * * ?")
// 每天早上9点执行
@Scheduled(cron = "0 0 9 * * ?")
// 每10秒执行
@Scheduled(fixedRate = 10000)
四、如何避免任务重复执行?
Spring 默认定时任务是串行执行的。如果任务耗时较长,可能导致下次调度错过。
解决方式:
@EnableAsync
@EnableScheduling
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar registrar) {
registrar.setScheduler(Executors.newScheduledThreadPool(5));
}
}
五、@Async:异步任务执行
1. 开启异步支持
@SpringBootApplication
@EnableAsync
public class MyApplication {}
2. 异步执行方法
@Component
public class EmailService {
@Async
public void sendEmail(String to) {
// 模拟耗时操作
Thread.sleep(3000);
System.out.println("发送邮件到:" + to);
}
}
3. 调用异步方法
@Autowired
private EmailService emailService;
@GetMapping("/notify")
public String notifyUser() {
emailService.sendEmail("[email protected]");
return "邮件发送中(异步)";
}
六、自定义线程池(推荐)
默认线程池可配置,以避免使用默认的 SimpleAsyncTaskExecutor。
@Configuration
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-task-");
executor.initialize();
return executor;
}
}
七、定时 + 异步的组合用法
某些定时任务本身比较耗时,可直接结合:
@Scheduled(fixedRate = 10000)
@Async
public void syncData() {
System.out.println("执行异步数据同步任务:" + LocalDateTime.now());
}
八、使用 Spring Boot 配置控制定时任务
你可以在 application.yml
中控制是否启用某些定时任务:
my:
task:
enabled: true
结合条件注解:
@Scheduled(cron = "0 0 * * * ?")
@ConditionalOnProperty(name = "my.task.enabled", havingValue = "true")
public void doTask() {
...
}
九、异常处理与监控建议
- 使用 try-catch 保证定时任务不会异常终止
- 记录任务执行日志
- 接入 Prometheus / Micrometer 监控任务执行耗时
十、总结
组件 | 用途 |
---|---|
@Scheduled | 定时任务调度 |
@Async | 异步任务执行 |
SchedulingConfigurer | 自定义线程池管理任务 |
AsyncConfigurer | 自定义异步执行线程池 |
通过这两个注解,你可以轻松构建高并发、低耦合的任务执行系统。
下一篇将聚焦在 Java Web 实战中常用的缓存技术:
《Java 缓存实战:使用 Redis + Spring Cache 优化性能》
是否继续生成第 8 篇?