定时任务实现的几种方式:
Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
Spring Task:Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。
Quartz:这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。(如果SpringBoot版本是2.0.0以后的,则在spring-boot-starter中已经包含了quart的依赖,则可以直接使用spring-boot-starter-quartz
依赖)
项目中需要实现一个每天凌晨定期清理缓存的功能,感觉上Quartz太重了,就选择了Spring Task,简单易实现
使用时,首先在启动类中加上@EnableScheduling注解来开启定时任务
@SpringBootApplication @EnableScheduling //开启计划任务支持 public class SpringtaskApplication { public static void mainString[] args) { SpringApplication.runSpringtaskApplication.class, args); } }
然后就可以实现自己的功能了
@Scheduled是定时任务的注解
@Scheduled有三种定时任务的执行方式,包括fixedDelay、fixedRate、corn表达式
fixedDelay:指定两次任务执行的时间间隔毫秒),此时间间隔指的是,前一次任务结束与下一个任务开始的间隔。如:@ScheduledfixedDelay = 5*1000 ),表示第一个任务结束后,过5秒后,开始第二个任务。
fixedRate:指定两次任务执行的时间间隔毫秒),此时间间隔指的是,前一个任务开始与下一个任务开始的间隔。如:
@ScheduledfixedRate= 5*1000 ),表示第一个任务开始后第一个任务执行时间小于5秒),第一个任务开始后的第6秒,开始第二个任务。如果第一个任务执行时间大于5秒,第一个任务结束后,直接开始第二个任务。
cron:通过表达式来配置任务执行时间
如果任务执行长度超过周期,且为单线程,结果如下图:(图来源:https://blog.csdn.net/applebomb/article/details/52400154)
cron表达式详解
一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。按顺序依次为:
秒(0~59)
分钟(0~59)
小时(0~23)
天(0~31)
月(0~11)
星期(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
年份(1970-2099)(可选)
“/”:表示为“每”,如“0/10”表示每隔10分钟执行一次,“0”表示为从“0”分开始, “3/20”表示表示每隔20分钟执行一次 “?”:只用于月与周,表示不指定值 “*” 代表整个时间段。 “L”:只用于月与周,5L用在月表示为每月的最后第五天天;1L用在周表示每周的最后一天; “W”::表示有效工作日周一到周五),只能出现在day-of-month,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 “#”:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。 “C”:代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。 注意:每个元素可以是一个值如6),一个连续区间9-12),一个间隔时间8-18/4)/表示每隔4小时),一个列表1,3,5),通配符。由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置‘?’
一些网上找的实例
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点 0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时 0 0 12 ? * WED 表示每个星期三中午12点 "0 0 12 * * ?" 每天中午12点 "0 15 10 ? * *" 每天上午10:15 "0 15 10 * * ?" 每天上午10:15 "0 15 10 * * ? *" 每天上午10:15 "0 15 10 * * ? 2005" 2005年的每天上午10:15 "0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟 "0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟 "0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟 "0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟 "0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44 "0 15 10 ? * MON-FRI" 周一至周五的上午10:15 "0 15 10 15 * ?" 每月15日上午10:15 "0 15 10 L * ?" 每月最后一日的上午10:15 "0 15 10 ? * 6L" 每月的最后一个星期五上午10:15 "0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15 "0 15 10 ? * 6#3" 每月的第三个星期五上午10:15
完成我的任务,每天0点定时清理缓存
@Component public class TestSchedule { @Scheduledcron = "0 0 0 * * ?") //每天零点执行 public void printDate){ System.out.printlnnew Date).toString));
xxxxxxx } }
当定时任务很多的时候,为了提高任务执行效率,可以采用并行方式执行定时任务,任务之间互不影响, 只要实现SchedulingConfigurer接口就可以。