热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

SpringBoot下使用定时任务的方式全揭秘(6种)

这篇文章主要介绍了SpringBoot下使用定时任务的方式全揭秘(6种),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

本文旨在用通俗的语言讲述枯燥的知识

定时任务作为一种系统调度工具,在一些需要有定时作业的系统中应用广泛,如每逢某个时间点统计数据、在将来某个时刻执行某些动作...定时任务在主流开发语言均提供相应的API供开发者调用,在Java中,实现定时任务有很多种方式,原生的方式实现一个完整定时任务需要由Timer、TimerTask两个类,Timer是定时器类,用来按计划开启后台线程执行指定任务,TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务。除此之外,还可以用ScheduledExecutorService类或者使用第三方jar库Quartz,其中Quartz是一个优秀的定时任务框架,发展至今已经非常成熟,以致后来其他的定时任务框架的核心思想或底层大多源于Quartz。

springboot作为Java的一种开发框架,在springboot项目中实现定时任务不仅可以使用Java提供的原生方式,还可以使用springboot提供的定时任务API,下面,小编把Java原生和springboot所有的实现定时任务的方式做一个整合。

文章提纲:
1、使用线程
2、使用Timer类
3、使用ScheduledExecutorService类
4、使用Quartz
5、使用spring的@Scheduled注解
6、cron表达式

1. 线程实现

利用线程可以设定休眠时间的方式可以实现简单的定时任务逻辑。

  public static void main(String[] args){
    //定时任务间隔时间
    int sleepTime=2*1000;
    new Thread(new Runnable() {
      @Override
      public void run() {
        while (true){
          try {
            System.out.println("Thread方式执行一次定时任务");
            //线程休眠规定时间
            Thread.sleep(sleepTime);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }

2. Timer类

Timer类允许调度一个TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行。

  public static void main(String[] args){
    int sleepTime=2*1000;
    TimerTask timerTask = new TimerTask() {
      @Override
      public void run() {
        System.out.println("Timer方式执行一次定时任务");
      }
    };
    new Timer().schedule(timerTask,1,sleepTime);
  }

3. ScheduledExecutorService类

ScheduledExecutorService,是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。

因此,基于ScheduledExecutorService类的定时任务类,归根到底也是基于线程的调度实现的。

  public static void main(String[] args){
    int sleepTime=2*1000;
    ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
    scheduledExecutor.scheduleAtFixedRate(
        new Runnable() {
          @Override
          public void run() {
            System.out.println("ScheduledExecutorService方式执行一次定时任务");
          }
        }
    ,1,sleepTime, TimeUnit.SECONDS);
  }

4. 整合Quartz

Quartz是一个完全由Java编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制,要理解它的使用方式,需要先理解它的几个核心概念:

Job: 表示一个工作,要执行的具体内容。此接口中只有一个方法,如下:
void execute(JobExecutionContext context)

  1. JobDetail: 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
  2. Trigger: 代表一个调度参数的配置,什么时候去调。
  3. Scheduler: 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。

有了这些概念之后,我们就可以把Quartz整合到我们的springboot项目中了。

引入quartz依赖


  org.springframework.boot
  spring-boot-starter-quartz

配置

@Configuration
public class QuartzConfig {
  @Bean
  public JobDetail quartzDetail(){
    return JobBuilder.newJob(QuartzTest.class).withIdentity("QuartzTest").storeDurably().build();
  }
  @Bean
  public SimpleTrigger quartzTrigger(){
    SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInSeconds(10)
        .repeatForever();
    return TriggerBuilder.newTrigger().forJob(quartzDetail())
        .withIdentity("QuartzTest")
        .withSchedule(scheduleBuilder)
        .build();
  }
}

测试

public class QuartzTest extends QuartzJobBean {
  @Override
  protected void executeInternal(JobExecutionContext jobExecutionContext){
    System.out.println("quartz执行一次定时任务 ");
  }
}

5. 使用Scheduled注解

@Scheduled是spring为定时任务而生的一个注解,查看注解的源码:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
//cron表达式
  String cron() default "";
//接收一个java.util.TimeZone#ID。
  String zone() default "";
//上一次执行完毕时间点之后多长时间再执行
  long fixedDelay() default -1;
//支持占位符形式的字符串类型的fixedDelay
  String fixedDelayString() default "";
//上一次开始执行时间点之后多长时间再执行
  long fixedRate() default -1;
//支持占位符形式的字符串类型的fixedRateString
  String fixedRateString() default "";
//第一次延迟多长时间后再执行  
  long initialDelay() default -1;
//支持占位符形式的字符串类型的initialDelay
  String initialDelayString() default "";
}

可以看出:Scheduled注解中的参数用来设置“定时”动作,通常情况下,比较常用的参数是cron(),这意味着我们需要学会一些cron表达式相关的语法,但由于内容较多,篇幅较长,在这里暂不铺开讲解,我们把cron语法相关放到文章最后,在此先讲解如何用Scheduled注解来实现定时任务。

开启定时任务支持

@SpringBootApplication
/**
 * 开启定时任务支持
 */
@EnableScheduling
public class TestApplication extends SpringBootServletInitializer {
  public static void main(String[] args) {
    SpringApplication.run(TestApplication.class, args);
  }
  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    return builder.sources(this.getClass());
  }
}

使用

@Component
public class ScheduledTest {
  private Logger logger = LoggerFactory.getLogger(ScheduledTest.class);
  /**
   * 每15秒执行一次定时任务
   */
  @Scheduled(cron = "0/15 * * * * ? ")
  public void testCron(){
    logger.info("Scheduled 执行一次定时任务");
  }
}

6. cron表达式

cron表达式是一个字符串其语法为:

[秒] [分] [小时] [日] [月] [周] [年]

其中[年]为非必填项,因此通常cron表达式通常由6或7部分内容组成,内容的取值为数字或者一些cron表达式约定的特殊字符,这些特殊字符称为“通配符”,每一个通配符分别代指一种值。cron表达式可以用这样的表格来表示:

顺序 取值范围 特殊字符串范围
0~60 , - * /
0-60 , - * /
0-23 , - * /
1-31 , - * /
1-12 / JAN-DEC , - * ? / L W
1-7 / SUN-SAT , - * ? / L #
年(可省略) 1970-2099 , - * /

其中通配符的解释以及作用如下:

通配符 代表的值 解释
* 所有值 如:时字段为*,代表每小时都触发
? 不指定值 如:周字段为?,代表表达式不关心是周几
- 区间 如:时字段设置2-5,代表2,3,4,5点钟时都触发
, 多个值 如:时字段设置2,3,5,代表2,3,5点都会触发
/ 递增值 如:时字段设置0/2,代表每两个小时触发,时字段设置 2/5,代表从2时开始每隔5小时触发一次
L 最后值 如:日字段设置L,代表本月最后一天
W 最近工作日 如:在日字段设置13W,代表没约13日最近的那个工作日触发一次
# 序号 如:在周字段设置5#2,代表每月的第二个周五

示例:
每2秒执行一次:0/5 ?
每5分钟执行一次:0 0/5 * ?
1分、12分、45分执行一次:0 1,12,45 * ?
每天23点59分59秒执行一次:59 59 23 ?
每月15号凌晨3点执行一次:0 0 3 15 * ?
每月最后一天12点执行一次:0 0 12 L * ?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 本文介绍了电流源并联合并的方法,以及谐振电路的原理。谐振电路具有很强的选频能力,通过将电感和电容连接在一起,电流和电压会产生震荡。谐振频率的大小取决于电感和电容的大小,而电路中的电阻会逐渐降低震荡的幅度。电阻和电容组成的电路中,当电容放完电后,电阻两端的电压为0,电流不再流过电容。然而,电感是一种特殊的器件,当有电流流过时,线圈会产生感应磁场,阻止电流的流动,从而使电流不会减小。 ... [详细]
  • 标题: ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • 本文介绍了在Docker容器技术中限制容器对CPU的使用的方法,包括使用-c参数设置容器的内存限额,以及通过设置工作线程数量来充分利用CPU资源。同时,还介绍了容器权重分配的情况,以及如何通过top命令查看容器在CPU资源紧张情况下的使用情况。 ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • position属性absolute与relative的区别和用法详解
    本文详细解读了CSS中的position属性absolute和relative的区别和用法。通过解释绝对定位和相对定位的含义,以及配合TOP、RIGHT、BOTTOM、LEFT进行定位的方式,说明了它们的特性和能够实现的效果。同时指出了在网页居中时使用Absolute可能会出错的原因,即以浏览器左上角为原始点进行定位,不会随着分辨率的变化而变化位置。最后总结了一些使用这两个属性的技巧。 ... [详细]
  • 开发笔记:Docker 上安装启动 MySQL
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Docker上安装启动MySQL相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
author-avatar
金针菇滚滚夹着五根水葱
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有