Spring @Scheduler使用cron表达式时的执行问题详解

 更新时间:2018年09月09日 11:46:46   作者:苍枫露雨  
Spring给程序猿们带来了许多便利。下面这篇文章主要给大家介绍了关于Spring @Scheduler使用cron表达式时的执行问题的相关资料,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧

前言

Spring Scheduler里有两个概念:任务(Task)和运行任务的框架(TaskExecutor/TaskScheduler)。TaskExecutor顾名思义,是任务的执行器,允许我们异步执行多个任务。TaskScheduler是任务调度器,来运行未来的定时任务。触发器Trigger可以决定定时任务是否该运行了,最常用的触发器是CronTrigger。Spring内置了多种类型的TaskExecutor和TaskScheduler,方便用户根据不同业务场景选择。

本文主要介绍了关于Spring @Scheduler使用cron表达式执行问题的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧

主要想弄清使用Spring @Scheduler cron表达式时的两个问题:

  • 同一定时任务,第二次触发时间到了,第一次还没有执行完成时会执行吗?
  • 不同的定时任务,相互之间是否有影响?

结论写在前面:

  • 同一定时任务,第二次触发时间到了,第一次还没有执行完成时会执行吗?不会,会等前一次执行完成才执行下一次
  • 不同的定时任务,相互之间是否有影响?取决于可用的定时任务线程数,如果线程数足够则不会影响;如果可用定时任务线程数少于要执行定时任务数量,未能获取到线程的自然要等到有空闲线程时才能执行。

下面是实验过程。。。。。

使用Spring @Scheduler 时,默认只有一个线程,针对上面的问题,设计了3个实验:

  1. 设置Scheduler为多线程,设置一个线程5秒执行一次,方法体为 sleep8秒
  2. 使用Scheduler默认的单线程,设置两个线程都是5秒执行一次,一个 sleep8秒,一个不sleep
  3. 设置Scheduler为多线程,设置两个线程都是5秒执行一次,一个 sleep8秒,一个不sleep

实验一

设置Scheduler为多线程,设置一个线程5秒执行一次,方法体为 sleep8秒:

 @Scheduled(cron = "*/5 * * * * *")
 public void test1() throws InterruptedException {
 log.info("test1, 5秒执行一次,每次执行sleep 8s");
 Thread.sleep(8000L);
 }

结果:

2017-10-11 17:49:45 scheduler-1 test1, 5秒执行一次,每次执行sleep 8
2017-10-11 17:49:55 scheduler-1 test1, 5秒执行一次,每次执行sleep 8
2017-10-11 17:50:05 scheduler-1 test1, 5秒执行一次,每次执行sleep 8
2017-10-11 17:50:15 scheduler-2 test1, 5秒执行一次,每次执行sleep 8
2017-10-11 17:50:25 scheduler-2 test1, 5秒执行一次,每次执行sleep 8
2017-10-11 17:50:35 scheduler-1 test1, 5秒执行一次,每次执行sleep 8

结论:

@Scheduled使用cron表达式,设置为多线程时,同一任务前一次没有执行完成,不会执行下一次

实验二

使用Scheduler默认的单线程,设置两个线程都是5秒执行一次,一个 sleep8秒,一个不sleep

如果test2每8秒执行一次,则为串行

 @Scheduled(cron = "*/5 * * * * *")
 public void test1() throws InterruptedException {
 System.out.println("test1, 5秒执行一次,每次执行sleep 8s");
 Thread.sleep(8000L);
 }

 @Scheduled(cron = "*/5 * * * * *")
 public void test2() {
 System.out.println("test2, 5秒执行一次,不sleep");
 }

执行结果:

2017-10-11 17:17:35 test2, 5秒执行一次,不sleep
2017-10-11 17:17:35 test1, 5秒执行一次,每次执行sleep 8s
2017-10-11 17:17:43 test2, 5秒执行一次,不sleep
2017-10-11 17:17:45 test1, 5秒执行一次,每次执行sleep 8s
2017-10-11 17:17:53 test2, 5秒执行一次,不sleep
2017-10-11 17:17:55 test2, 5秒执行一次,不sleep
2017-10-11 17:17:55 test1, 5秒执行一次,每次执行sleep 8s
2017-10-11 17:18:03 test2, 5秒执行一次,不sleep
2017-10-11 17:18:05 test2, 5秒执行一次,不sleep
2017-10-11 17:18:05 test1, 5秒执行一次,每次执行sleep 8s
2017-10-11 17:18:13 test2, 5秒执行一次,不sleep
2017-10-11 17:18:15 test1, 5秒执行一次,每次执行sleep 8s
2017-10-11 17:18:23 test2, 5秒执行一次,不sleep
2017-10-11 17:18:25 test1, 5秒执行一次,每次执行sleep 8s

对比期望执行时间:

执行次数 task 期望执行时间 实际执行时间
1 task1 17:17:35 17:17:35
1 task2 17:17:35 17:17:35
2 task1 17:17:40 17:17:43
2 task2 17:17:40 17:17:45

结论:

@Scheduled使用cron表达式 ,配置为一个线程时,不同定时任务是串行执行,且上次没有执行完时不会执行下次

实验三

设置Scheduler为多线程,设置两个线程都是5秒执行一次,一个 sleep8秒,一个不sleep

 @Scheduled(cron = "*/5 * * * * *")
 public void test1() throws InterruptedException {
  log.info("test1, 5秒执行一次,每次执行sleep 8s");
  Thread.sleep(8000L);
 }

 @Scheduled(cron = "*/5 * * * * *")
 public void test2() {
  log.info("test2, 5秒执行一次,不sleep");
 }

结果:

2017-10-11 18:12:40 scheduler-2 test2, 5秒执行一次,不sleep
2017-10-11 18:12:40 scheduler-1 test1, 5秒执行一次,每次执行sleep 8s
2017-10-11 18:12:45 scheduler-2 test2, 5秒执行一次,不sleep
2017-10-11 18:12:50 scheduler-1 test1, 5秒执行一次,每次执行sleep 8s
2017-10-11 18:12:50 scheduler-2 test2, 5秒执行一次,不sleep
2017-10-11 18:12:55 scheduler-2 test2, 5秒执行一次,不sleep
2017-10-11 18:13:00 scheduler-1 test1, 5秒执行一次,每次执行sleep 8s

对比期望执行时间:

执行次数 task 期望执行时间 实际执行时间
1 task1 18:12:40 18:12:40
1 task2 18:12:40 18:12:40
2 task1 18:12:45 18:12:50
2 task2 18:12:45 18:12:45

结论:

@Scheduled使用cron表达式 ,配置为多线程时,不同定时任务不是串行执行,且上次没有执行完时不会执行下次

设置定时任务为多线程

这里用的是spring boot:

@Configuration
public class ScheduleConfig {

 @Bean
 public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
  ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
  scheduler.setPoolSize(3);
  scheduler.setThreadNamePrefix("scheduler-");
  return scheduler;
 }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • Java服务端如何解决跨域问题 CORS请求头方式

    Java服务端如何解决跨域问题 CORS请求头方式

    这篇文章主要介绍了Java服务端如何解决跨域问题 CORS请求头方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • java多线程导入excel的方法

    java多线程导入excel的方法

    最近项目写了poi导入excel数据到数据库,想把学到的知识用于实践,于是使用多线程方式导入excel,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • JAVA8 的StringJoiner 使用及原理解析

    JAVA8 的StringJoiner 使用及原理解析

    这篇文章主要介绍了JAVA8 的StringJoiner 使用及原理解析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • SpringBoot常见错误图文总结

    SpringBoot常见错误图文总结

    最近在使用idea+Springboot开发项目中遇到一些问题,这篇文章主要给大家介绍了关于SpringBoot常见错误总结的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • 深入理解Java中的Lambda表达式

    深入理解Java中的Lambda表达式

    这篇文章主要介绍了深入理解Java中的Lambda表达式,Lambda在各编程语言中都是非常重要的特性,而Java中则加入得有些太晚...需要的朋友可以参考下
    2015-07-07
  • 基于Springboot+Vue实现的在线答题闯关系统全过程

    基于Springboot+Vue实现的在线答题闯关系统全过程

    这篇文章主要介绍了基于Springboot+Vue实现的在线答题闯关系统的相关资料,文中包括前端Vue.js、后端SpringBoot及MySQL数据库的使用,系统功能涵盖顺序出题、体型练习、随机出题、错题本、收藏题和答题统计等,需要的朋友可以参考下
    2024-12-12
  • Springboot中使用lombok的@Data注解方式

    Springboot中使用lombok的@Data注解方式

    这篇文章主要介绍了Springboot中使用lombok的@Data注解方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • spring cloud eureka注册原理-注册失败填坑笔记

    spring cloud eureka注册原理-注册失败填坑笔记

    这篇文章主要介绍了spring cloud eureka注册原理-注册失败填坑笔记,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • SpringBoot整合Redis实现缓存分页数据查询功能

    SpringBoot整合Redis实现缓存分页数据查询功能

    类似淘宝首页,这些商品是从数据库中查出来的吗,答案肯定不是,本文我们就通过一个案例实操一下,首页热点数据怎么放到Redis中去查询,感兴趣的同学可以参考一下
    2023-06-06
  • Spring整合Quartz分布式调度的示例代码

    Spring整合Quartz分布式调度的示例代码

    本篇文章主要介绍了Spring整合Quartz分布式调度的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04

最新评论