一:简述定时任务
定时任务经常有文章拿Scheduled、Quartz、Timer进行比较,确实三者的差距还是比较明显的。而且对于一个初学者并不是很友好,特别是Scheeduled、Quartz容易搞混。这篇文章将专门介绍Spring提供的定时任务Scheduled使用方法及注意事项,后面再讲解Quartz定时任务然后再做比较。至于Timer比较简单,一笔带过即可
二:XML配置
经过前面Spring的AOP以及事务应用讲解,一般发现Spring都会提供XML配置与注解两种方式,下面就先讲解XML配置的方式实现
2.1 定时任务类
就是比较简单的一个类方法,打印定时任务执行线程名称和执行时间。别忘了把这个类交给Spring容器管理,当然采用注解亦或是配置文件中注入都是可以的
2.2 Spring配置文件
配置文件中声明定时任务类、方法、执行时间是最简单的配置。如下表所示,配置定时任务属性说明
属性名称 | 属性含义 | 备注 |
---|---|---|
ref | 引入容器中管理的定时任务对象 | |
method | 声明定时任务执行方法的名称 | |
fixed-delay | 定时任务执行间隔周期 | 周期从上一次定时任务执行完毕开始计算 |
fixed-rate | 定时任务执行间隔周期 | 周期从上一次定时任务开始执行计算 |
initial-delay | 第一次执行延时时长 | 系统启动后距离多久才开始执行第一次定时任务 |
cron | cron表达式用于指定复杂逻辑定时任务 | 下面详细解释 |
三:Cron表达式
3.1 表达式概述
表达式总共七个部分,含义为:“秒 分 时 日期 月 星期几 [年]”
其中年不是必填项,所以Cron表达式可能也只有六部分
区域 | 属性值 | 可用特殊字符 | 备注 |
---|---|---|---|
秒 | 0-59 | * , - / | |
分 | 0-59 | * , - / | |
时 | 0-59 | * , - / | |
日期 | 1-31 | * , - / ? L W | |
月 | 1-12 | * , - / | |
星期几 | 1-7 | * , - / L # | 1表示星期日 |
年 | 1970~2099 | * , - / | 可以省略 |
3.2 特殊字符
看不懂没关系,概念解释起来就是麻烦。不理解的字符查看表达式示例即可
字符 | 含义 | 说明 |
---|---|---|
* | 所有 | |
- | 范围 | |
? | 日期与星期几互斥,当其中一个指定值时另外一个避免冲突需要置为? | |
, | 与的关系 | 时上写10,11 表示上午10点和11点 |
/ | 前面为开始条件,后面为间隔周期 | 时上写1/2表示从上午1点开始,每间隔2小时执行一次 |
L | 最后 | 星期几上写2L 表示当月最后一个星期三 |
W | 有效工作日(周一到周五) | 只能出现在日期上,5W表示当5号为周六非工作日时会在4号周五执行,若表示为周天非工作日则会安排在6号周一执行。注意不能跨月 |
LW | 最后一个工作日 | |
# | 第几个星期几 | 5#2 表示第2个星期4执行 |
3.3 表达式示例
表达式描述 | 表达式示例 |
---|---|
每天零点执行 | 0 0 0 * * * |
每周1-5下午五点执行 | 0 0 17 ? * 2-6 |
每月最后一个周五上午10点和下午5点执行 | 0 0 10,17 ? * 6L |
3.4 星期几说明
Spring中的周几与Cron表达式不一致,0才表示周天。所以这是巨特么坑,千万别用数字来操作,草他妈。看清楚源码的操作是将周一到周天全部转换为0-6数字操作的。。。。。。
四:多线程配置
4.1 线程池配置
Scheduled定时任务默认是单线程执行,那么A任务执行可能会影响到B任务。即当B任务到达执行时间时,若A任务未执行完毕,因为单线程原因只能等待A任务执行完毕后再开始执行。可如下通过配置定时任务线程池解决
4.2 多线程测试
如4.1所示配置两个定时任务实例,将定时任务1修改睡眠2S,查看最后执行结果如下图所示,不仅线程名称切换且查看定时任务2执行间隔也为配置时长2S。线程池id属性为线程名称前缀
五:注解
5.1 开启注解
开启注解很简单就是配置annotation-driven即可,多线程配置也是一致
5.2 注解使用
六:单任务多线程
6.1 单任务单线程
定时任务设定fixedRate为2s执行一次,但是控制台显示为4s执行一次,也就是线程睡眠时间。前面讲到fixedRate是从上一个任务开始时间计时,按照原理来讲上一个任务未执行完毕时下一个任务已经到了执行时间,而且配置文件中配置了Scheduled为多线程,为什么还会是等到上一个任务执行完毕后再执行?这就是Scheduled相对于Quartz的一个特殊点,多线程指的是不同任务间多线程,相同任务只能是串行执行
6.2 单任务多线程
可以看到这里单个定时任务已经多线程执行,结合Spring的异步执行即可实现。更多有关Spring异步执行操作后面会有文章专门介绍