WHAT
@Scheduled 由Spring定义,用于将方法设置为调度任务。如:方法每隔十秒钟被执行、方法在固定时间点被执行等
@Scheduled(fixedDelay = 1000)
上一个任务结束到下一个任务开始的时间间隔为固定的1秒,任务的执行总是要先等到上一个任务的执行结束@Scheduled(fixedRate = 1000)
每间隔1秒钟就会执行任务(如果任务执行的时间超过1秒,则下一个任务在上一个任务结束之后立即执行)@Scheduled(fixedDelay = 1000, initialDelay = 2000)
第一次执行的任务将会延迟2秒钟后才会启动@Scheduled(cron = “0 15 10 15 * ?”)
Cron表达式,每个月的15号上午10点15开始执行任务在配置文件中配置任务调度的参数
@Scheduled(fixedDelayString = “${fixedDelay.in.milliseconds}”)
@Scheduled(fixedRateString = “${fixedRate.in.milliseconds}”)
@Scheduled(cron = “${cron.expression}”)
WHY
@Scheduled使用方便,不需要自己去写复杂的任务调度。注解的方式非常灵活,只需要在方法上添加@Scheduled注解就能定义调度的任务,任何无参的方法都可以瞬间成为供调度的任务
1 | /** |
HOW
Spring是如何实现如此简洁的任务调度定义的?怎么使用@Scheduled?
- Requirements
- Spring容器中需要创建 Bean: ScheduledAnnotationBeanPostProcessor
- Spring容器中需要有TaskScheduler实现类的实例
- 无参方法添加@Scheduled注解
扩展
扩展有两种方式
- 实现SchedulingConfigurer接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// 优先级高
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler());
}
@Bean(destroyMethod = "shutdown")
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("poolmary&mark");
scheduler.setPoolSize(50);
return scheduler;
}
} - 创建TaskScheduler的实现Bean
1
2
3
4
5
6
7
8// 相对实现SchedulingConfigurer接口的方式,优先级低
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("poolScheduler");
scheduler.setPoolSize(50);
return scheduler;
}
原理
- ScheduledAnnotationBeanPostProcessor的postProcessAfterInitialization方法将@Scheduled的方法包装为指定的task添加到ScheduledTaskRegistrar中
- ScheduledAnnotationBeanPostProcessor会监听Spring的容器初始化事件,在Spring容器初始化完成后进行TaskScheduler实现类实例的查找,若发现有SchedulingConfigurer的实现类实例,则跳过3
- 查找TaskScheduler的实现类实例默认是通过类型查找,若有多个实现则会查找名字为”taskScheduler”的实现Bean,若没有找到则在 ScheduledTaskRegistrar调度任务的时候会创建一个newSingleThreadScheduledExecutor,将TaskScheduler的实现类实例设置到ScheduledTaskRegistrar属性中
- ScheduledTaskRegistrar的scheduleTasks方法触发任务调度
- 真正调度任务的类是TaskScheduler实现类中的ScheduledExecutorService,由J.U.C提供
事例
1 | @Configuration |
Music is the strongest form of magic. - 1900