顶部左侧内容
百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 在线教程 > 正文

你需要的spring定时任务讲解+案例都在这里

gosiye 2024-08-19 14:56 6 浏览 0 评论

本文目录

  • 定时任务概述、原理
  • 基于注解(@Scheduled)的定时任务
  • 基于接口(SchedulingConfigurer)的定时任务
  • 可更改时间的定时任务

一、定时任务概述、原理

概述:开发中经常会使用到定时任务,顾名思义,定时任务就是定时执行的方法,即定时执行的代码。比如,为了减少服务器或者数据库的压力,我们会将一些对服务器或者数据库等有压力的高频操作,改为定时去执行,例如每晚凌晨0点同步A系统的数据到B系统,每2小时统计用户的积分情况,每周一给支付宝用户推送上周收入支出数据报表等。一 般情况下,很多业务处理会定时在凌晨处理,因为避开了户使用高峰期,服务器资源充足,而且对用户影响小。

原理:spring在初始化bean后,通过“postProcessAfterInitialization”拦截到所有的用到“@Scheduled”注解的方法,并解析相应的的注解参数,放入“定时任务列表”等待后续处理;之后再“定时任务列表”中统一执行相应的定时任务(任务为顺序执行,先执行cron,之后再执行fixedRate)。

二、基于注解(@Scheduled)的定时任务

  需要注意的是@Scheduled默认是串行的,单线程,当开启多个任务时,任务的执行时机会受上一个任务执行时间的影响。

@Configuration

@EnableScheduling //开启定时任务

public class ScheduleTask {

//每10秒执行一次

@Scheduled(cron = "0/10 * * * * ?")

private void configureTasks() {

System.out.println("我是一个定时任务");

}

}

@Scheduled 除了cron还提供另外三种种方式: fixedRate,fixedDelay,initialDelay

1、cron表达式可以定制化执行任务,但是执行的方式是与fixedDelay相近的,也是会按照上一次方法结束时间开始算起。

2、fixedDelay控制方法执行的间隔时间,是以上一次方法执行完开始算起,如上一次方法执行阻塞住了,那么直到上一次执行完,并间隔给定的时间后,执行下一次。

@Configuration

@EnableScheduling //开启定时任务

public class ScheduleTask {

//每10秒执行一次

@Scheduled(fixedDelay = 10000)

private void configureTasks() {

System.out.println("我是一个定时任务");

}

}

3、fixedRate是按照一定的速率执行,是从上一次方法执行开始的时间算起,如果上一次方法阻塞住了,下一次也是不会执行,但是在阻塞这段时间内累计应该执行的次数,当不再阻塞时,一下子把这些全部执行掉,而后再按照固定速率继续执行。

@Configuration

@EnableScheduling //开启定时任务

public class ScheduleTask {

//每10秒执行一次

@Scheduled(fixedRate = 10000)

private void configureTasks() {

System.out.println("我是一个定时任务");

}

}

  4、initialDelay = 10000 表示在容器启动后,延迟10秒后再执行一次定时器。

@Configuration

@EnableScheduling //开启定时任务

public class ScheduleTask {

//容器启动后,延迟10秒后再执行一次定时器,以后每10秒再执行一次该定时器。

@Scheduled(initialDelay = 10000, fixedRate = 10000)

private void configureTasks() {

System.out.println("我是一个定时任务");

}

}

三、基于接口(SchedulingConfigurer)的定时任务

  有些程序员可能发现,使用@Scheduled 注解很方便,但缺点是当我们调整了执行周期的时候,需要重启应用才能生效,这多少有些不方便。为了达到实时生效的效果,那么可以使用接口来完成定时任务。

  下面案例从数据中获取执行周期时间,然后动态执行定时任务:

@Configuration

@EnableScheduling //开启定时任务

public class DynamicScheduleTask implements SchedulingConfigurer {

//从数据获取任务执行周期

@Autowired

private MyBatisMapper myBatisMapper;

@Override

public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

taskRegistrar.addTriggerTask(

//1.添加任务内容(Runnable)

() -> System.out.println("执行动态定时任务: " + LocalDateTime.now().toLocalTime()),

//2.设置执行周期(Trigger)

triggerContext -> {

//2.1从数据库获取执行周期

String cron = myBatisMapper.getCron();

//2.2 返回执行周期(Date)

return new CronTrigger(cron).nextExecutionTime(triggerContext);

}

);

}

}

数据库表数据如下:

现在,我们启动测试看看

执行动态定时任务: 17:17:00.008999

执行动态定时任务: 17:17:20.002501

执行动态定时任务: 17:17:30.001786

执行动态定时任务: 17:17:40.005512

执行动态定时任务: 17:17:50.005870

执行动态定时任务: 17:18:00.002189

执行动态定时任务: 17:18:10.001910

我们可以看到每10秒执行一次任务。那么现在要求每5秒执行一次,该怎么做呢?这个时候我们只需要修改下数据库数据即可,无需重启。

现在,我们再看看控制台打印的是什么?

执行动态定时任务: 17:18:30.000902

执行动态定时任务: 17:18:40.001392

执行动态定时任务: 17:18:45.005027

执行动态定时任务: 17:18:50.001367

执行动态定时任务: 17:18:55.001356

执行动态定时任务: 17:19:00.001582

执行动态定时任务: 17:19:05.005676

执行动态定时任务: 17:19:10.001258

执行动态定时任务: 17:19:15.005272

成功每5秒执行一次。是不是很有成就感,哈哈

四、可更改时间的定时任务

案例如下:

  package com.nobody.task;

  import org.slf4j.Logger;

  import org.slf4j.LoggerFactory;

  import org.springframework.scheduling.Trigger;

  import org.springframework.scheduling.annotation.SchedulingConfigurer;

  import org.springframework.scheduling.config.ScheduledTaskRegistrar;

  import org.springframework.scheduling.support.CronTrigger;

  import org.springframework.stereotype.Component;

  /**

  * @Description 可动态更改时间的定时任务

  * @Author Mr.nobody

  * @Date 2021/3/4

  * @Version 1.0.0

  */

  @Component

  public class ChangeTimeScheduledTask implements SchedulingConfigurer {

  private static final Logger LOGGER = LoggerFactory.getLogger(ChangeTimeScheduledTask.class);

  // cron表达式,我们动态更改此属性的值即可更改定时任务的执行时间

  private String expression = "0/5 * * * * *";

  @Override

  public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

  // 定时任务要执行的方法

  Runnable task = () -> LOGGER.info(">>> configureTasks ...");

  // 调度实现的时间控制

  Trigger trigger = triggerContext -> {

  CronTrigger cronTrigger = new CronTrigger(expression);

  return cronTrigger.nextExecutionTime(triggerContext);

  };

  taskRegistrar.addTriggerTask(task, trigger);

  }

  public String getExpression() {

  return expression;

  }

  public void setExpression(String expression) {

  this.expression = expression;

  }

  }

接口调用:

  package com.nobody.controller;

  import com.nobody.task.ChangeTimeScheduledTask;

  import org.springframework.web.bind.annotation.GetMapping;

  import org.springframework.web.bind.annotation.RequestMapping;

  import org.springframework.web.bind.annotation.RestController;

  /**

  * @Description

  * @Author Mr.nobody

  * @Date 2021/3/4

  * @Version 1.0.0

  */

  @RestController

  @RequestMapping("demo")

  public class DemoController {

  private ChangeTimeScheduledTask changeTimeScheduledTask;

  public DemoController(final ChangeTimeScheduledTask changeTimeScheduledTask) {

  this.changeTimeScheduledTask = changeTimeScheduledTask;

  }

  @GetMapping

  public String testChangeTimeScheduledTask() {

  changeTimeScheduledTask.setExpression("0/10 * * * * *");

  return "ok";

  }

  }

  启动服务,没调用接口之前,定时任务是每5秒执行一次

  2021-03-04 14:02:10.001 INFO 6836 --- [TaskScheduler-1] com.nobody.task.ChangeTimeScheduledTask : >>> configureTasks ...

  2021-03-04 14:02:15.001 INFO 6836 --- [TaskScheduler-1] com.nobody.task.ChangeTimeScheduledTask : >>> configureTasks ...

  2021-03-04 14:02:20.002 INFO 6836 --- [TaskScheduler-1] com.nobody.task.ChangeTimeScheduledTask : >>> configureTasks ...

  2021-03-04 14:02:25.001 INFO 6836 --- [TaskScheduler-1] com.nobody.task.ChangeTimeScheduledTask : >>> configureTasks ...

  然后我们调用接口,改变定时任务的时间,结果变为每10秒执行一次。

  2021-03-04 14:02:30.005 INFO 6836 --- [TaskScheduler-1] com.nobody.task.ChangeTimeScheduledTask : >>> configureTasks ...

  2021-03-04 14:02:35.002 INFO 6836 --- [TaskScheduler-1] com.nobody.task.ChangeTimeScheduledTask : >>> configureTasks ...

  2021-03-04 14:02:40.001 INFO 6836 --- [TaskScheduler-1] com.nobody.task.ChangeTimeScheduledTask : >>> configureTasks ...

完!

相关推荐

全球最大的H5网站模板库(h5页面模板下载)

当今社会,互联网迅猛发展,在网络营销中,客户往往通过企业的网站建设留下对该企业的第一印象,一个优秀的企业网站已成为企业发展的重要纽带,嗨创H5,拥有国内外一流的技术团队,潜心专研网站建设6年,是全球最...

wordpress集团公司网站模板:XSgr(wordpress建站公司)

小兽wordpress推出一款高端集团公司主题,打造高品质官网。高端是一种态度和坚持,因为我坚信贴合产品及品牌理念的高端深度定制才能最大化地呈现企业的务实严谨与产品的专业品质相比,某种程度上讲–...

私心推荐,小编酷爱的五款高逼格网站模板

建站宝盒的网站模板上千套之多,各有各的风格色彩,但是,弱水三千,小编我却只取一瓢饮,在这上千套模板之中,小编酷爱的网站模板有五套,让小编私心推荐一下吧!1、茶叶贸易公司网站模板小编对这款网站模板可是一...

「书讯」政府网站用户行为研究与应用

《政府网站用户行为研究与应用》作者:刘合翔著出版日期:2018年6月开本:16开出版社:经济管理出版社小编推荐《政府网站用户行为研究与应用》的主题是关于政府网站用户行为的特征规律及其在政府网站优...

免费服务器-搭建模板网站的操作流程(图文版)

之前发文《创业者的官网:如何搭建免费云服务器及操作面板(图文版)》,因为做了视频才发现,创业者对视频的需求,远远低于对图文解说的需求。因此,补充图文教程,不清楚的看官们,可以直接看视频版本进行细部学...

快收藏这些高逼格H5网站模板吧,不绕弯子直接下载

上面这些响应式H5网站是不是很炫酷,比起那些“在线一键生成”是不是好太多了?关键是,那些一键制作都不会开放源码给你,自定义性也很局限。不过说到底还是难看。今天笔者推荐大家一个模板网站,全都是高质量的响...

如何开发网站建设管理系统模板(如何开发网站建设管理系统模板图片)

根据用户网站需求文档设计美工图,并设计数据库结构,让网站开发人员可以更多地关注前台美工,先对照美工图,编写静态HTML页面,按网站建设管理系统模板语法,修改编写好的静态HTML页面,运行。不再需要对...

C语言的数据类型介绍(c语言的数据类型介绍是什么)

在计算机系统中,数据是放在内存中的,数字、文字、符号、图形、音频、视频等数据都是以二进制形式存储在内存中的,它们并没有本质上的区别,那么0001000该理解为数字8呢,还是图像中某个像素的颜色...

C 语言格式化输出函数中常用的格式符号

在之前介绍输入输出函数的文章中,有提到格式化输入输出函数都有包含一种特殊的符号——格式符号。那篇文章中关于格式符号也只是一笔带过,没有进行深入挖掘。本篇文章主要对输出函数(printf)中的一些常用格...

C#中的类型转换(c#数据转换类)

计算机存储的基本单位:字节我们知道一个字节(Byte)有8个比特(bit)构成,比特是存储的最小单位,表示0和1,但为什么计算机存储的基本单位是字节,而不是比特呢?假设我们要存储数字3(二进制:11...

Java8中String内存空间占用分析(电脑里下载的文件怎样删除才不会占用内存空间)

1.前言分析之前,简单回顾一下对象的内存分布。在HotSpot虚拟机中,对象在堆内存中的存储布局可以划分为三部分:对象头、实例数据和对齐填充。对象头包含两部分内容:MarkWord和类型指针。实例数据...

「每日C语言」数据类型大小和取值范围

对于c语言来说,数据类型是一个很重要的概念和知识点,它涉及到的是内存的空间,这在和硬件交互的时候是非常重要的。K&R给出了7个数据类型相关的关键字,分别是:int、long、short、uns...

【c语言学习笔记】数据类型(c语言里面的数据类型)

c语言学习笔记,欢迎大家能在评论区提出我学习错误的地方方便我进行改正~在计算机中,计算机用二进制来储存数据,在c语言中有许多的数据类型用来存储数据,当然不同的数据类型所用的内存占用也不一样,下面就来用...

关于MySQL varchar类型最大值,原来一直都理解错了

我是架构精进之路,点击上方“关注”,坚持每天为你分享技术干货,私信我回复“01”,送你一份程序员成长进阶大礼包。写在前面关于MySQLvarchar字段类型的最大值计算,也许我们一直都理解错误了,...

C语言数据类型的转换(c语言数据类型的转换方式)

类型转换在C语言程序中,经常需要对不同类型的数据进行运算,为了解决数据类型不一致的问题,需要对数据的类型进行转换。例如一个浮点数和一个整数相加,必须先将两个数转换成同一类型。C语言程序中的类型...

取消回复欢迎 发表评论: