在SpringBoot中定时任务一般使用的是@Scheduled注解。

@Scheduled

1.注解内容:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
String CRON_DISABLED = "-"; String cron() default ""; String zone() default ""; long fixedDelay() default -1L; String fixedDelayString() default ""; long fixedRate() default -1L; String fixedRateString() default ""; long initialDelay() default -1L; String initialDelayString() default "";
}

2.注解说明

@Target:表示@Schduled可以被使用在方法和注解上。
@Retention:表示@Schduled的生命周期是在程序运行时。
@Repeatable:表示@Schduled可以被在同一个地方重复使用多次,参数存放在Schedules类中(我们可以点进去看Schedules类,发现里面有一个Scheduled数组对象,用来保存多个Scheduled的配置)。

3.注解属性

String CRON_DISABLED:定时禁用标志。
String cron():定义定时执行时间,默认值"",表示该值无效。
String zone():定义时区,默认值""。
long fixedDelay():定义任务下次开始执行的间隔时间,从上一次任务执行完成开始计算,单位毫秒。默认值-1L,表示该值设置无效。
String fixedDelayString():定义任务下次开始执行的间隔时间,从上一次任务执行完成开始计算,单位毫秒。与fixedDelay不同只在于值的格式。默认值"",表示该值设置无效。
long fixedRate():定义每两次任务的间隔频率,从上一次任务开始执行开始计算,单位毫秒。默认值-1L,表示该值无效。
String fixedRateString():定义每两次任务的间隔频率,从上一次任务开始执行开始计算,单位毫秒。与fixedRate不同只在于值的格式。默认值"",表示该值无效。
long initialDelay():定义第一次执行的延迟执行时间,单位秒。默认值-1L,表示没有延迟。
String initialDelayString():定义第一次执行的延迟执行时间,与initialDelayDelay()不同在于这里使用表达式,而不是以秒为单位。默认值"",表示没有延迟。

4.样例说明

4.1 corn

    @Scheduled(cron="0/2 * * * * *") //从0秒开始,每间隔2秒执行一次,参数说明在5,这里只要知道这个意思就行。
public void scheduling2() {
System.out.println("开始休眠" + new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束休眠" + new Date());
}

上面例子中,我们配置了corn属性,令该任务每两秒执行一次,但是在方法体中我们又设定了方法的执行至少需要5秒。因此当定时任务开始执行下一次任务的时候,上一次任务仍然没有执行结束,时间上会存在一个冲突,我们查看控制台输出的结果是如下:

开始休眠Tue Jul 09 15:54:58 CST 2019
结束休眠Tue Jul 09 15:55:03 CST 2019
开始休眠Tue Jul 09 15:55:04 CST 2019
结束休眠Tue Jul 09 15:55:09 CST 2019

从结果可以看到,任务之间的时间间隔并不是我们指定的2秒执行一次,而是变成了6秒。这既不是我们指定的任务间隔2秒,也不是我们指定的任务执行时长5秒。

我们总结一下规律可以发现:使用corn指定时间,指定的不是任务之间的间隔时间,而是任务的开始执行时间。即我们如上配置,是指当时间在0秒,2秒,4秒……58秒的时候,会尝试开始执行任务。如果发现上一次任务没有执行结束,那么本次不会启动新的任务,同时跳过本次执行,等待下次时间达到。

由此,我们不难发现出现上面结果的原因,第一次开始执行是在54:58,第二次到达时间是55:00,此时由于任务仍没有结束,因此跳过本次执行。再下一次时间到达55:02,这时候任务仍然没有结束,继续跳过。当时间到达55:03时,任务结束,打印我们的输出语句,再然后达到下一次的任务启动时间55:04,这时上一次任务已经执行完成,重新启动新一次的任务。

4.2fixedDelay、fixedDelayString

    @Scheduled(fixedDelay = 2000) //每2秒执行一次
//@Scheduled(fixedDelayString="2000") //意义同上,每两秒执行一次
public void scheduling2() {
System.out.println("开始休眠" + new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束休眠" + new Date());
}

在这里,我们配置了fixedDelay属性,令任务每2秒执行一次,同时方法体中又设定了执行时间需要5秒。我们查看一下输出结果:

开始休眠Tue Jul 09 16:29:21 CST 2019
结束休眠Tue Jul 09 16:29:26 CST 2019
开始休眠Tue Jul 09 16:29:28 CST 2019
结束休眠Tue Jul 09 16:29:33 CST 2019

与corn不同的是,这里不是指定某个时间开始执行任务,而是计算每两次任务之间的时间间隔,且是从上一次任务执行结束的时间开始计算。

即假如任务完成需要5秒,设置间隔时间2秒,那么下一次任务的执行时间应该是7秒后开始执行。

4.3fixedRate、fixedRateString

    @Scheduled(fixedRate = 2000) //每2秒执行一次。
//@Scheduled(fixedRateString="2000") //每2秒执行一次
public void scheduling2() {
System.out.println("开始休眠" + new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束休眠" + new Date());
}

在这里我们配置了fixedRate属性,设定每2秒执行一次,但是方法体中同样设定了任务执行需要5秒。我们查看输出结果:

开始休眠Tue Jul 09 15:59:50 CST 2019
结束休眠Tue Jul 09 15:59:55 CST 2019
开始休眠Tue Jul 09 15:59:55 CST 2019
结束休眠Tue Jul 09 16:00:00 CST 2019

与corn和fixedDelay不同的是,从结果上看fixedRate是在我们方法体执行完成后,立即开始执行下一次的任务。这只是因为我们的方法执行时间大于设定的间隔时间,其实也就是说,fixedRate的间隔是从任务开始执行时候计算,但是由于间隔时间已到,但任务仍未执行完成,需要等待任务执行完成后,才立即执行下一次任务。

即下次任务的执行时间=当前时间+(执行频率 > 当前任务的执行时间 ? 执行频率 : 当前任务的执行时间)

例如:每次任务执行需要5s,fixedRate设定每2秒执行一次,第一次执行时间10:00:00,那么第二次任务执行时间=10:00:00+(2 > 5 ? 2 : 5)=10:00:05

4.4initialDelay、initialDelayString

这两个字段通常用来配合corn、fixedRate、fixedDelay进行设置。指定程序开始运行时的第一次执行的延迟时间。

例如设置initialDelay=10*1000,表示任务会在程序启动10秒后第一次运行(默认是程序启动后立即运行)。

5.参数格式

这里的参数格式主要说的是corn的格式,因为其他的属性都可以用long类型来作为以毫秒为单位的时间参数。

corn=1 * * * * * *

corn后可以以" "空格为间隔添加7个参数,从左至右依次表示:

  1. 秒:取值范围0-60
  2. 分:取值范围0-60
  3. 时:取值范围0-23
  4. 日:取值范围1-31
  5. 月:取值范围1-12
  6. 星期:取值范围1-7,同时也可以以星期的英文缩写,如周日sun
  7. 年:取值范围1970-2099,这个值可以省略不写。

除了直接用数字表示外,也可以使用通配符"*,?-/"

  • *:表示可以取任意值,如2 * * * * *,表示每分钟的第二秒执行任务
  • ,:表示多个取值,如3,6,9 * * * * *,表示每分钟的第3秒,第6秒,第9秒都会执行任务。
  • ?:只能使用在日期和星期上,表示值不确定,和*差不多。
  • -:表示时间范围,如0-30 * * * * *,表示每分钟的前30秒每秒执行一次。
  • /:表示时间段,一般是x/y格式,x表示起始时间,y表示步长,如0/2 * * * * *,表示从0开始,每两秒执行一次任务。

6.corn、fixedDelay、fixedRate区别

定义:

corn:定义任务在某个/某些特定的时间点执行,以指定的时间为准,而不是任务。例如每周一早上8点零五分执行程序,corn=0 5 8 * * 1。

fixedDelay:定义任务下一次开始执行的时间间隔,以任务执行时间为准。即本次任务执行完成后,到下次任务开始执行前的时间间隔。从任务执行完成开始计算时间。

fixedRate:定义任务每隔多久执行一次,以任务执行时间为准。即任务开始执行后,到下次任务开始执行前的时间间隔。从任务开始执行开始计算时间。

应用场景:

corn:多应用在某个特定的时间点/段开始执行的某些任务。

fixedDelay:多应用在某些需要循环执行的任务。一般用在单任务场景,或必须要前一个任务执行完成,才能执行后一个任务的场景。

fixedRate:多应用在某些需要循环执行的任务。一般用在多任务场景,配合线程池,当时间间隔达到,就将任务丢给线程池去执行,可以同时运行任务多次,任务与任务之间互不干扰。

结束。

最新文章

  1. Boba.js – 用于 Google 统计分析 JavaScript 库
  2. NOIP2009靶形数独[DFS 优化]
  3. JS实现屏蔽键盘操作
  4. Class to connect postgres with python in psycopg2
  5. 4.给定一个正整数m,统计m的位数,分别打印每一位数字,再按照逆序打印出各位数字。 要求:m定义为类的属性,需定义构造函数为m赋值;当m大于99999时,输出错误信息“the number is too large”,不再执行。
  6. 多线程(三)GCD
  7. linux下 yum源、rpm、源代码安装mysql
  8. 【转】qtp安装时问题
  9. java+tomcat 在 linux下的部署
  10. Matlab中用内建函数代替for循环
  11. vb ——ini 配置文件
  12. Javascript 风格向导
  13. wpf做的3d滑动gallery
  14. Unity Singleton 单例类(Unity3D开发之二十)
  15. Lambda in Java VS in C#
  16. iOS 计算所有标注的经纬度范围 来确定地图显示区域
  17. 推送GitHub报错 fatal: Out of memory, malloc failed 解决办法
  18. 实现一个string类
  19. JSONObject,String,Map互相转换
  20. Oracle存储过程基础

热门文章

  1. 0818NOIP模拟测试赛后总结
  2. java定时器demo
  3. github上创建java项目简单操作
  4. python生成word中文字体
  5. STL 最大堆与最小堆
  6. 图解SQL的Join
  7. PAT甲级——A1075 PAT Judge
  8. myeclipse启动jboss报ERROR [MainDeployer] Could not create deployment
  9. java主函数参数传递args
  10. 如何给Apache Pig自定义UDF函数?