SpringBoot定时任务(三十三)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
二八佳人体似酥腰间仗剑斩愚夫。虽然不见人头落暗里教君骨髓枯。
上一章简单介绍了SpringBoot系统启动任务(三十二)的方式,如果没有看过,请观看上一章
定时任务主要使用的是 @Scheduled 注解
关于 Cron 表达式 可以看老蝴蝶之前的文章:
https://blog.csdn.net/yjltx1234csdn/article/details/105846493
SpringBoot 使用 @Scheduled 定时任务
pom.xml 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
application.yml 配置
server:
port: 8081
servlet:
context-path: /Job
添加 @EnableScheduling 注解
@SpringBootApplication
//开启定时任务的注解
@EnableScheduling
@Log4j2
public class JobApplication {
public static void main(String[] args) {
SpringApplication.run(JobApplication.class,args);
log.info("运行定时任务启动成功");
}
}
定时任务配置类
@Component
@Log4j2
public class MyJob {
}
fixedRate 和 fixedDelay 属性
fixedRate 表示任务执行之间的时间间隔具体是指两次任务的开始时间间隔。 但可能存在第二次任务开始时第一次任务还没有结束的可能。
fixedDelay 表示任务执行之间的时间间隔 具体是指本次任务结束到下次任务开始之间的时间间隔。
单位都是毫秒
fixedRate
//每2秒执行一次是上一次启动和这一次启动的时间间隔
@Scheduled(fixedRate = 2000)
public void job1(){
sayHello();
}
public void sayHello(){
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String now=simpleDateFormat.format(new Date());
System.out.println(">>>你好当前时间是:"+now);
}
启动程序:
>>>你好当前时间是:2023-01-03 17:12:17.389
2023-01-03 17:12:17.398 INFO 13768 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '/Job'
2023-01-03 17:12:17.400 INFO 13768 --- [ restartedMain] top.yueshushu.learn.JobApplication : Started JobApplication in 2.163 seconds (JVM running for 2.645)
2023-01-03 17:12:17.400 INFO 13768 --- [ restartedMain] top.yueshushu.learn.JobApplication : 运行定时任务启动成功
>>>你好当前时间是:2023-01-03 17:12:19.390
>>>你好当前时间是:2023-01-03 17:12:21.390
>>>你好当前时间是:2023-01-03 17:12:23.391
大概每隔两秒执行一次
fixedDelay
//每2秒执行一次是上一次结束和这一次启动的时间间隔
@Scheduled(fixedDelay = 2000)
public void job2(){
sayHello();
}
启动程序: 后面的毫秒数是依次递增的 因为 执行 sayHello() 方法 也需要一个时间.
>>>你好当前时间是:2023-01-03 17:16:00.148
2023-01-03 17:16:00.157 INFO 33904 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '/Job'
2023-01-03 17:16:00.158 INFO 33904 --- [ restartedMain] top.yueshushu.learn.JobApplication : Started JobApplication in 1.685 seconds (JVM running for 2.205)
2023-01-03 17:16:00.159 INFO 33904 --- [ restartedMain] top.yueshushu.learn.JobApplication : 运行定时任务启动成功
>>>你好当前时间是:2023-01-03 17:16:02.149
>>>你好当前时间是:2023-01-03 17:16:04.151
>>>你好当前时间是:2023-01-03 17:16:06.152
>>>你好当前时间是:2023-01-03 17:16:08.154
>>>你好当前时间是:2023-01-03 17:16:10.156
>>>你好当前时间是:2023-01-03 17:16:12.157
>>>你好当前时间是:2023-01-03 17:16:14.158
>>>你好当前时间是:2023-01-03 17:16:16.159
>>>你好当前时间是:2023-01-03 17:16:18.161
添加睡眠程序使方法执行时间变长 这个效果就很明显了。
执行程序时间过长 fixedRate 和 fixedDelay 区别
休眠 3s, 超过了任务执行的频率
@Scheduled(fixedRate = 2000)
public void job3() throws Exception{
log.info(">>>>fixedRate 进来了");
Thread.sleep(3000);
}
@Scheduled(fixedDelay = 2000)
public void job31() throws Exception{
log.info(">>>>fixedDelay 进来了");
//休眠 3000s
Thread.sleep(3000);
}
fixedRate:
2023-01-03 17:19:57.320 INFO 4624 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedRate 进来了
2023-01-03 17:20:00.321 INFO 4624 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedRate 进来了
2023-01-03 17:20:03.322 INFO 4624 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedRate 进来了
2023-01-03 17:20:04.255 INFO 4624 --- [_ClusterManager] o.s.s.quartz.LocalDataSourceJobStore : ClusterManager: detected 1 failed or restarted instances.
2023-01-03 17:20:04.255 INFO 4624 --- [_ClusterManager] o.s.s.quartz.LocalDataSourceJobStore : ClusterManager: Scanning for instance "Yuejl1672737568619"'s failed in-progress jobs.
2023-01-03 17:20:04.338 INFO 4624 --- [_ClusterManager] o.s.s.quartz.LocalDataSourceJobStore : ClusterManager: ......Freed 1 acquired trigger(s).
2023-01-03 17:20:06.323 INFO 4624 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedRate 进来了
2023-01-03 17:20:09.323 INFO 4624 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedRate 进来了
2023-01-03 17:20:12.324 INFO 4624 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedRate 进来了
每隔 3s 执行一次。
fixedDelay:
2023-01-03 17:22:47.771 INFO 29908 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedDelay 进来了
2023-01-03 17:22:47.780 INFO 29908 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '/Job'
2023-01-03 17:22:47.782 INFO 29908 --- [ restartedMain] top.yueshushu.learn.JobApplication : Started JobApplication in 1.545 seconds (JVM running for 2.032)
2023-01-03 17:22:47.782 INFO 29908 --- [ restartedMain] top.yueshushu.learn.JobApplication : 运行定时任务启动成功
2023-01-03 17:22:47.794 INFO 29908 --- [_MisfireHandler] o.s.s.quartz.LocalDataSourceJobStore : Handling 1 trigger(s) that missed their scheduled fire-time.
2023-01-03 17:22:52.773 INFO 29908 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedDelay 进来了
2023-01-03 17:22:57.774 INFO 29908 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedDelay 进来了
2023-01-03 17:23:02.776 INFO 29908 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedDelay 进来了
2023-01-03 17:23:07.782 INFO 29908 --- [ scheduling-1] top.yueshushu.learn.jobConfig.MyJob : >>>>fixedDelay 进来了
发现 每隔 5s (2s+3s) 执行一次。
使用 fixedDelay 执行的时间与任务方法执行的花费时间有关 可能时间并不是真实要使用的时间。
建议 使用 fixedRate 来表示频率。
initialDelay 首次任务启动的延迟时间
//initialDelay 首次任务启动的延迟时间
@Scheduled(initialDelay = 3000,fixedRate = 2000)
public void job4() throws Exception{
sayHello();
}
程序启动成功 3s后 再执行定时任务, 再以2s 的频率执行
2023-01-03 17:27:07.556 INFO 2996 --- [ restartedMain] top.yueshushu.learn.JobApplication : 运行定时任务启动成功
2023-01-03 17:27:07.640 INFO 2996 --- [_MisfireHandler] o.s.s.quartz.LocalDataSourceJobStore : Handling 1 trigger(s) that missed their scheduled fire-time.
>>>你好当前时间是:2023-01-03 17:27:10.546
>>>你好当前时间是:2023-01-03 17:27:12.547
>>>你好当前时间是:2023-01-03 17:27:14.545
Cron 表达式
cron 表达式: 3/2 * * * * *
// cron 表达式
@Scheduled(cron = "3/2 * * * * *")
public void job5() throws Exception{
sayHello();
}
2023-01-03 17:29:02.002 INFO 7296 --- [ main] top.yueshushu.learn.JobApplication : 运行定时任务启动成功
2023-01-03 17:29:02.069 INFO 7296 --- [_MisfireHandler] o.s.s.quartz.LocalDataSourceJobStore : Handling 1 trigger(s) that missed their scheduled fire-time.
>>>你好当前时间是:2023-01-03 17:29:03.002
>>>你好当前时间是:2023-01-03 17:29:05.001
>>>你好当前时间是:2023-01-03 17:29:07.014
Cron 业务调用
定义一个 业务操作 UserService.addUser
@Service
@Log4j2
public class UserServiceImpl implements UserService {
@Override
public void addUser(User user) {
log.info("执行添加员工的操作");
}
}
//里面使用 userService 实例
@Resource
private UserService userService;
@Scheduled(cron = "3/2 * * * * *")
public void job6() throws Exception{
//执行任务复杂的情况不建议使用.
// 采用 quartz 的方式实现
userService.addUser(null);
}
2023-01-03 17:32:48.882 INFO 7816 --- [ main] top.yueshushu.learn.JobApplication : 运行定时任务启动成功
2023-01-03 17:32:48.883 INFO 7816 --- [_MisfireHandler] o.s.s.quartz.LocalDataSourceJobStore : Handling 1 trigger(s) that missed their scheduled fire-time.
2023-01-03 17:32:49.002 INFO 7816 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:32:51.001 INFO 7816 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:32:53.002 INFO 7816 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:32:55.001 INFO 7816 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
业务调用也是可以的。
异步方法调用
当执行任务方法花费时间过长时 异步处理
@Override
public void addUser(User user) {
try{
TimeUnit.SECONDS.sleep(3);
}catch (Exception e){
}
log.info("执行添加员工的操作");
}
不异步之前
变成了 每隔 4s 执行一次了。
2023-01-03 17:35:35.681 INFO 11884 --- [ main] top.yueshushu.learn.JobApplication : 运行定时任务启动成功
2023-01-03 17:35:35.699 INFO 11884 --- [_MisfireHandler] o.s.s.quartz.LocalDataSourceJobStore : Handling 1 trigger(s) that missed their scheduled fire-time.
2023-01-03 17:35:40.001 INFO 11884 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:35:44.003 INFO 11884 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:35:48.002 INFO 11884 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:35:52.008 INFO 11884 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:35:56.002 INFO 11884 --- [ scheduling-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
异步
添加 @EnableAsync 注解
@SpringBootApplication
//开启定时任务的注解
@EnableScheduling
@EnableAsync
@Log4j2
public class JobApplication {
public static void main(String[] args) {
SpringApplication.run(JobApplication.class,args);
log.info("运行定时任务启动成功");
}
}
任务方法上添加 @Async 注解
@Override
@Async
public void addUser(User user) {
try{
TimeUnit.SECONDS.sleep(3);
}catch (Exception e){
}
log.info("执行添加员工的操作");
}
执行, 每隔 2s 执行一次。
2023-01-03 17:38:48.338 INFO 8916 --- [ main] top.yueshushu.learn.JobApplication : 运行定时任务启动成功
2023-01-03 17:38:48.416 INFO 8916 --- [_MisfireHandler] o.s.s.quartz.LocalDataSourceJobStore : Handling 1 trigger(s) that missed their scheduled fire-time.
2023-01-03 17:38:52.022 INFO 8916 --- [ task-1] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:38:54.002 INFO 8916 --- [ task-2] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:38:56.003 INFO 8916 --- [ task-3] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
2023-01-03 17:38:58.003 INFO 8916 --- [ task-4] t.y.learn.service.UserServiceImpl : 执行添加员工的操作
动态 Cron 配置
目前的 cron
@Component
@Log4j2
public class MyDynamicCronJob implements SchedulingConfigurer {
public static String helloCron = "3/2 * * * * *";
public void sayHello(){
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String now=simpleDateFormat.format(new Date());
System.out.println(">>>你好当前时间是:"+now);
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
() -> {
// 调用方法
sayHello();
},
new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
// 配置下一次执行时间
CronTrigger cronTrigger = new CronTrigger(helloCron);
return cronTrigger.nextExecutionTime(triggerContext);
}
}
);
}
}
方法动态改变 cron 的值
@RestController
public class CronController {
@RequestMapping("/setCron")
public String setCron() {
int maxRate = new Random().nextInt(10) +4;
String cron = "3/"+maxRate+" * * * * *";
MyDynamicCronJob.helloCron = cron;
return cron;
}
}
访问地址: http://localhost:8081/Job/setCron 改成了 7
>>>你好当前时间是:2023-01-03 18:56:19.001
2023-01-03 18:56:19.047 INFO 3360 --- [_MisfireHandler] o.s.s.quartz.LocalDataSourceJobStore : Handling 1 trigger(s) that missed their scheduled fire-time.
>>>你好当前时间是:2023-01-03 18:56:21.002
>>>你好当前时间是:2023-01-03 18:56:23.007
>>>你好当前时间是:2023-01-03 18:56:25.016
>>>你好当前时间是:2023-01-03 18:56:27.009
>>>你好当前时间是:2023-01-03 18:56:29.016
2023-01-03 18:56:30.201 INFO 3360 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/Job] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-01-03 18:56:30.201 INFO 3360 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2023-01-03 18:56:30.206 INFO 3360 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
>>>你好当前时间是:2023-01-03 18:56:31.005
>>>你好当前时间是:2023-01-03 18:56:38.001
>>>你好当前时间是:2023-01-03 18:56:45.002
动态 Cron 配置成功
本章节的代码放置在 github 上:
https://github.com/yuejianli/springboot/tree/develop/SpringBoot_Job
谢谢您的观看如果喜欢请关注我再次感谢 !!!