基于@Scheduled注解(静态配置)实现定时任务
前言
- 在Spring Boot中,定时任务通过简单的注解即可实现周期性任务的自动执行。
- 常用于数据统计、定时清理、通知推送等场景。
实现流程
1.启用定时任务
- 在主类或配置类添加 @EnableScheduling 注解
@SpringBootApplication
@EnableScheduling // 开启定时任务支持
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2.定义定时任务类
@Component
public class SimpleScheduledTask {
// 每5秒执行一次(固定速率,从任务开始时间算间隔)
@Scheduled(fixedRate = 5000)
public void task1() {
System.out.println("Fixed Rate Task: " + LocalDateTime.now());
}
// 每3秒执行一次(固定延迟,从任务结束时间算间隔)
@Scheduled(fixedDelay = 3000)
public void task2() {
System.out.println("Fixed Delay Task: " + LocalDateTime.now());
}
// 每天10:00执行(Cron表达式)
@Scheduled(cron = "0 0 10 * * ?")
public void task3() {
System.out.println("Cron Task: " + LocalDateTime.now());
}
}
- 关键参数说明
- Cron表达式格式【可通过相关网站设置并生成】
秒(0-59) 分(0-59) 时(0-23) 日(1-31) 月(1-12) 周(0-7,0和7均为周日)
注意事项
- 需要在启动类上添加注解支持@EnableScheduling,负责定时任务失效。
效果【观察输出日志】
拓展【其他实现方式】
1.动态任务配置(基于接口 SchedulingConfigurer)
- A.适用场景:
- 需要从数据库或配置文件动态加载任务配置
- 支持运行时动态增删改任务
- B.实现步骤
- (1)创建动态任务配置类:
@Configuration
@EnableScheduling
public class DynamicScheduledConfig implements SchedulingConfigurer {
@Autowired
private TaskConfigRepository taskConfigRepository; // 假设从数据库读取任务配置
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// 动态加载任务配置
List<TaskConfig> tasks = taskConfigRepository.findAllEnabledTasks();
tasks.forEach(task -> {
Runnable runnable = () -> executeTask(task);
Trigger trigger = context -> {
String cron = task.getCronExpression();
return new CronTrigger(cron).nextExecutionTime(context);
};
taskRegistrar.addTriggerTask(runnable, trigger);
});
}
private void executeTask(TaskConfig task) {
System.out.println("执行动态任务: " + task.getName() + ", 时间: " + LocalDateTime.now());
}
}
- (2)数据库实体示例:
@Entity
public class TaskConfig {
@Id
private String id;
private String name;
private String cronExpression;
private boolean enabled;
// Getters and Setters
}
2.多线程定时任务
- 解决单线程阻塞问题:默认情况下,@Scheduled 任务在单线程中串行执行。若需并行执行:
- 配置线程池
@Configuration
public class AsyncScheduledConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5); // 线程池大小
scheduler.setThreadNamePrefix("scheduled-task-");
scheduler.setAwaitTerminationSeconds(60);
scheduler.setWaitForTasksToCompleteOnShutdown(true);
return scheduler;
}
}
- 异步任务实例
@Component
public class AsyncScheduledTask {
// 异步 + 定时任务
@Async("taskExecutor") // 指定自定义线程池
@Scheduled(fixedRate = 5000)
public void asyncTask() {
System.out.println("异步任务线程: " + Thread.currentThread().getName());
}
}
总结
- 实际开发中,推荐优先使用 @Scheduled 注解快速实现简单任务,复杂场景结合动态配置和线程池优化。
- 生产环境务必添加任务监控和分布式锁机制。