SpringBoot中使用task实现定时任务

定时任务实现的几种方式:

  • 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 main(String[] args) {
        SpringApplication.run(SpringtaskApplication.class, args);
    }
}

然后就可以实现自己的功能了

@Scheduled是定时任务的注解
@Scheduled有三种定时任务的执行方式,包括fixedDelay、fixedRate、corn表达式
fixedDelay:指定两次任务执行的时间间隔(毫秒),此时间间隔指的是,前一次任务结束与下一个任务开始的间隔。如:@Scheduled(fixedDelay = 5*1000 ),表示第一个任务结束后,过5秒后,开始第二个任务。
fixedRate:指定两次任务执行的时间间隔(毫秒),此时间间隔指的是,前一个任务开始与下一个任务开始的间隔。如:
@Scheduled(fixedRate= 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 {
    @Scheduled(cron = "0 0 0 * * ?")  //每天零点执行
    public void printDate(){
        System.out.println(new Date().toString());
xxxxxxx } }

当定时任务很多的时候,为了提高任务执行效率,可以采用并行方式执行定时任务,任务之间互不影响, 只要实现SchedulingConfigurer接口就可以。

posted @ 2019-06-17 21:11  feifei97  阅读(2585)  评论(0编辑  收藏  举报