SpringTask定时任务怎么用?@Scheduled注解参数详解
基本概念
Spring Task 主要是用来实现定时任务的,定时任务的业务场景非常常见,比如:
① 数据定时备份
② 视频网站定时发布视频
③ 系统定时生成数据报表
我们可以直接使用 Spring 提供的 @Scheduled 注解即可定义定时任务,默认情况下,@Scheduled 的任务都在 Spring 创建的大小为 1 的默认线程池中执行(ScheduledThreadPoolExecutor)。
该注解常用的几个参数如下:
1.cron
使用 Cron 表达式定义任务的执行时间。Cron 表达式是一种用于调度任务的字符串,通常用于定义定时任务的执行时间。
它由六或七个字段组成,每个字段代表一个时间单位,依次为秒、分钟、小时、日期、月份、星期几和(可选的)年份。各字段通过空格分隔
在线 Cron 表达式生成器:http://cron.qqe2.com/
每一个字段的有效范围如下:
① 秒(Seconds):0-59
② 分钟(Minutes):0-59
③ 小时(Hours):0-23
④ 日期(Day of Month):1-31
⑤ 月份(Month):1-12 或 JAN-DEC
⑥ 星期几(Day of Week):0-7(0、7 表示星期天,1 表示星期二,以此类推)或 SUN-SAT
⑦ 年份(Year,可选):1970-2099
特殊字符:
① *:代表所有可能的值。例如,在秒字段为 * 表示每一秒触发
② ,:用于指定多个值。例如,在分钟字段中 5,10 表示第 5 和第 10 分钟
③ -:用于指定一个范围的值。例如,在小时字段中 1-5 表示从 1 点到 5 点每小时触发一次
④ /:表示起始时间开始触发,然后每隔固定时间触发一次。例如,在秒字段中 0/15 表示起始时间 0s 触发一次,之后每隔 15 秒触发一次
⑤ ?:只能在日期(Day of Month)和星期几(Day of Week)字段中使用,表示不指定值,在需要指定某一个字段而不关心另一个字段时使用。例如,想要在每月的 20 日触发而不管 20 日是星期几,则在 Day of Week 字段中使用 ?
⑥ L:只能在日期(Day of Month)和星期几(Day of Week)字段中使用,表示最后。例如,在 Day of Week 字段使用 5L 表示在最后一个星期四触发
⑦ W:只能在日期(Day of Month)字段中使用,表示工作日,系统将在离指定日期的最近的有效工作日触发事件。例如,在 Day of Month 中使用 5W,如果 5 日是星期六,则在 4 日(星期五)触发。如果 5 日是星期天,则在 6 日(周一)触发;如果 5 日是星期一到星期五中的一天,就在 5 日触发。另外,W 的最近寻找不会跨过月份
⑧ #:只能在日期(Day of Month)字段中使用,用于指定每月的第几个星期几。例如,2#1 表示某月的第一个星期一
示例:
(1)每天凌晨 1 点执行一次
0 0 1 * * *
(2)每隔5分钟执行一次
0 */5 * * * *
(3)每天下午 2 点到下午 2:05 期间,每 1 分钟执行一次
0 0-5 14 * * *
(4)每周一的早上 7 点执行一次
0 0 7 ? * MON
2.fixedRate
按固定的频率执行任务,从任务开始执行的时间算起,每隔固定的时间间隔重新执行一次,不管前一个任务是否完成
但这里需要注意的是,如果使用默认的方式,不修改线程池参数,即单线程执行,如果前一个任务执行时长大于定时时长,下一个任务的执行会等到上一个任务执行完后立即执行。但是如果增大线程池的线程数量,如果线程数量足够,下一个任务的执行不会被上一个任务所阻塞,而是会在定时结束后就立即执行,即出现任务并行执行的情况
举例:
(1)任务执行时间为 3s,间隔时间为 5s
- 第一次执行:0s 开始
- 第二次执行:5s 开始
- 第三次执行:10s 开始
(2)任务执行时间为 6s,间隔时间为 5s(单线程)
- 第一次执行:0s 开始
- 第二次执行:6s 开始
- 第三次执行:12s 开始
3.fixedDelay
在前一个任务完成后,等待固定的时间间隔再开始执行下一个任务
举例:
任务执行时间为 3s,间隔时间为 5s
- 第一次执行:0s 开始
- 第二次执行:3s(任务完成) + 5s(延迟时间) = 8s 开始
- 第三次执行: 11s(任务完成) + 5s(延迟时间) = 16s 开始
4.initialDelay
在应用启动后,初始延迟一定时间后开始任务,一般会配合 fixedRate 或 fixedDelay 使用,来指定延迟的时间
代码实现
1.在 Springboot 启动类加上 @EnableScheduling 注解,表示启用 Spring 框架中的计划任务调度功能
@SpringBootApplication
@EnableScheduling
public class TimedTaskDemoApplication {
public static void main(String[] args) {
SpringApplication.run(TimedTaskDemoApplication.class, args);
}
}
2.编写任务类,在定时任务方法上面加上 @Scheduled 注解,注意在类的上面要加上 @Component 注解。这里 根据四种常用的参数分别编写不同的任务
(1)cron
@Component
public class ScheduleTask {
@Scheduled(cron = "*/1 * * * * *") // 每秒执行一次
public void task1() {
System.out.println(LocalDateTime.now() + "定时任务");
}
}
测试结果:

(2)fixedRate
@Component
public class ScheduleTask {
private int times = 1;
@Scheduled(fixedRate = 5000) // 延迟 5s
public void task2() {
System.out.println(LocalDateTime.now() + "定时任务开始,当前次数:" + times);
try {
Thread.sleep(3000); // 执行 3s
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(LocalDateTime.now() + "定时任务结束,当前次数;" + times);
times++;
}
}
测试结果:

这里的延迟时间大于任务的执行时间,但当任务的执行时间大于了延迟时间,结果又会不相同,测试代码如下:
@Component
public class ScheduleTask {
private int times = 1;
@Scheduled(fixedRate = 5000) // 延时 5s
public void task3() {
System.out.println(LocalDateTime.now() + "定时任务开始,当前次数:" + times);
try {
Thread.sleep(7000); // 执行 7s
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(LocalDateTime.now() + "定时任务结束,当前次数;" + times);
times++;
}
}

可以看到,设定的延时时间为 5s,而实际上延迟的时间是 7s,原因在于默认线程池大小为 1,任务只能串行执行,后面的任务会受到前面任务执行耗时的影响
这里可以选择开启多线程,在类上方加上 @EnableAsync 注解,对应的方法上方加上 @Async 注解即可
@EnableAsync
@Component
public class ScheduleTask {
@Async
@Scheduled(fixedRate = 5000) // 延迟 5s
public void tasks4() {
System.out.println(LocalDateTime.now() + "定时任务开始,当前线程:" + Thread.currentThread());
try {
Thread.sleep(7000); // 执行 7s
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
测试结果:

可以看到此时的延时时间就是 5s
(3)fixedDelay
@Component
public class ScheduleTask {
private int times = 1;
@Scheduled(fixedDelay = 5000) // 延时 5s
public void task5() {
System.out.println(LocalDateTime.now() + "定时任务开始,当前次数:" + times);
try {
Thread.sleep(3000); // 执行 3s
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(LocalDateTime.now() + "定时任务结束,当前次数;" + times);
times++;
}
}
测试结果:

可以看到,下一次任务的开始时间是上一次任务的结束时间 + 延时时间
(4)initialDelay
@Component
public class ScheduleTask {
private int times = 1;
// 初始 1s,延时 5s
@Scheduled(initialDelay = 1000, fixedRate = 5000)
public void task6() {
System.out.println(LocalDateTime.now() + "定时任务开始,当前次数:" + times);
try {
Thread.sleep(3000); // 执行 7s
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(LocalDateTime.now() + "定时任务结束,当前次数;" + times);
times++;
}
}
测试结果:

可以看到,是在应用启动后 1s 开始第一次任务,随后每次延时了 5s
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Java的Comparable,Comparator和Cloneable三大接口详解
这篇文章主要为大家详细介绍了Java的Comparable,Comparator和Cloneable的接口,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助2022-03-03
Springboot开发之利用Docker和Kubernetes部署微服务
这篇文章主要介绍了如何将Spring Boot开发的微服务通过Docker容器化,并使用Kubernetes进行部署和管理,帮助读者掌握现代云原生应用的完整开发部署流程,有需要的可以了解下2025-03-03
详解JavaEE使用过滤器实现登录(用户自动登录 安全登录 取消自动登录黑用户禁止登录)
主要介绍用户的自动登录和取消自动登录,以及实现一天自动登录或者n天实现自动登录,当用户ip被加入到黑名单之后,直接利用过滤器返回一个警告页面。接下来通过本文给大家介绍JavaEE使用过滤器实现登录的相关知识,感兴趣的朋友一起学习吧2016-05-05
Spring security用户URL权限FilterSecurityInterceptor使用解析
这篇文章主要介绍了Spring security用户URL权限FilterSecurityInterceptor使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2019-12-12


最新评论