定时任务就是系统在特定的时间执行一段代码它的场景应用非常广泛:
1.购买游戏的月卡后,系统每天定时给会员发放游戏资源
2.管理系统定时生成报表
3.定时清理垃圾
实现定时任务的主要方式
1.Java自带的java.util.Timer类,这个类允许调度一个Java.util.TimerTask
任务。使用这种方式可以让程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
2.Quartz,这是一个功能强大的调度器,可以让程序在指定时间执行,也可以按照某一个频度执行,配置起来有点复杂
3.Spring3.0以后自带SpringTask,可以将它看成一个轻量级的Quartz,使用起来比Quarte简单许多。
使用步骤:
(1).在启动类上方添加@EnableScheduling注解
(2).在需要定时执行的方法上添加@Scheduled注解,@Scheduled(cron="******")
4.core表达式
Spring Task依靠Corn表达式配置定时规则。Cron表达式是一个字符串,分为六个或七个域,每一个域代表一个含义,以空格隔开。有如下两种语法格式:
(1)Seconds Minutes Hours DayofMonth Month DayofWeek Year
(2)Seconds Minutes Hours DayofMonth Month DayofWeek
Seconds(秒):域中可出现 ,- * / 四个字符,以及0-59的整数
*:表示匹配该域的任何值,在Seconds域中使用*,表示每秒钟都会触发
,:表示列出枚举值。在Seconds域中使用5,20表示在5秒和20秒各触发一次
-:表示范围。在Seconds域中使用5-20,表示从5秒到20秒每秒触发一次
/:表示起始时间开始触发,然后每隔固定时间触发一次。在Seconds域中使用5/20,表示5秒触发一次,25、45秒分别触发一次
Minutes(分):域中可以出现 , - * / 四个字符,以及0-59的整数
Hours(时):域中可以出现 , - * / 四个字符,以及0-23的整数
DayofMonth(日期):域中可出现 , - * / ?L W C 八个字符,以及1-31的整数
C:表示和当前日期关联。在DayofMonth使用5C,表示在五日后的那一天触发,并且每月的那天都会触发。比如当前是10号,则每月的15号都会触发。
L:表示最后,在DayofMonth中使用L,表示每个月最后一天触发
W:表示工作日,在DayofMonth中使用15W,表示最接近这个月的第15天的工作日触发,如果15日是星期六,那么就在14号星期五触发,如果15号是星期天,那么就在16号星期一触发,如果15号星期2,那么就在当天触发。该触发只会在当天触发,比如31W,31日是周日,那么是在29号星期五触发,而不是下月1日。注:在DayofMonth用LW表示在该月最后一个工作日触发。
Month:域中可以出现,- * / 四个字符 以及1-12的整数,或者JAN-DEC的单词缩写
DayofWeek(星期):可出现 ,- * / ?L # C八个字符,以及1-7的整数或SUN-SAT的缩写,1代表星期天,7代表星期六
C:在DayofWeek域使用2C,表示在2日后的那一天触发,且每周的那天都会触发。比如当前是周一,那么每周三会触发
L:在DayofWeek中使用L,代表在一周的最后一天即星期六触发,在DayofWeek中使用5L,代表在一个月的最后一个星期四触发
#:用来指定具体的周数,#前面代表星期几,#后面代表一个月的第几周,比如5#3代表一个月第三周的星期四
?:用于无法确定具体哪一天或者具体星期几使用,用于DayofMonth或者DayofWeek,例如在每月的20日0点触发,无法确定是星期几,所以Core表达式写为:0 0 0 20 * ? 或者在每月的最后一个星期日的零点触发,无法确定是多少号,Core表达式写为: 0 0 0 ? * 1L
Year(年份):域中可出现- * / 四个字符,以及1970~2099的整数。该域可以省略,表示每年都触发。
@Scheduled注解写在方法的上方,指定该方法定时执行。常用参数如下
1.core:core表达式
2.fixedDelay:任务立即执行,之后每隔多久执行一次,单位为毫秒,上一次任务结束后再开始计算下一次执行的时间 @Scheduled(fixedDelay=5000)
3.fixedRate:任务立即执行,之后每隔多久执行一次,单位是毫秒,上一次任务开始后开始计算下次执行的时间
4.initialDelay:项目启动后不马上执行定时器,根据initialDelay的值延时执行。
@Scheduled(fixedRast=5000,initalDelay=3000)项目三秒后启动,之后每5秒执行一次
注意!:Spring Task定时器默认是单线程的如果项目中使用多个定时器,使用一个线程会造成效率低下。因此需要创建线程池
首先1.写一个配置类(添加@Configuration注解),继承SchedulingConfigurer接口,重写configureTasks方法,方法里面的参数是 ScheduledTaskregistrar scheduledTaskregistrar
2.创建线程池
scheduledTaskregistrar .setScheduler(Executors.newScheduledThreadPool(5));线程池里面有5个线程