你需要的spring定时任务讲解+案例都在这里
yuyutoo 2024-10-12 00:07 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 ...
完!
相关推荐
- Visio 2019中文版软件下载及安装教程
-
下载地址见公众号内...
- 游戏系统设计经验分享:系统的了解认知与实现
-
讨论游戏系统设计前,首先需要对系统和游戏系统有一定的认知。能够较为独立的完成特定功能或玩法的一整套逻辑、数据与表现就是一个游戏系统。这样,游戏系统可分为功能性系统和玩法性系统。功能性系统是游戏中方便玩...
- 信息系统项目管理师综合知识:面向对象方法
-
【面向对象方法】来源:《信息系统项目管理师教程(第3版)》第1章信息化和信息系统P141.2.2面向对象方法...
- 2025年最好用的绘图软件有哪些?推荐5款绘图软件,教你快速画图
-
去年,我还在为如何绘制项目流程图提高工作效率而苦恼,今年,经过我的总结和比较,2025年最好用的5款绘图软件最新出炉,它们不仅让我的工作效率翻倍,还让我对于绘图有了更深的了解。想知道有哪些吗?今天就给...
- 在线白板工具:解锁创意与协作的新维度
-
一直觉得白板是个很好的工具,不管是学习还是工作,它都能够帮助我们更好地整理思路。作为一名经常需要远程协作和创意脑暴的职场人,显然传统普通的白板工具已经不够用了。在这个数字化时代,我们更需要一个电子白板...
- 这10个功能模块,手把手教你从零设计电商系统
-
导读:电商业务与我们的生活息息相关,大家可能对电商多少也有一些了解,事实上,即使是一个最小化的电商系统,也依然是非常复杂的。所以,我们先花一点时间,一起以一个创业公司的CTO的视角,设计一个最小化的电...
- 职业本科软件工程实训室建设初探
-
一、引言随着信息技术的飞速发展,软件工程在现代科技领域的重要性日益凸显。为了培养适应社会需求的高素质软件工程人才,高校和相关教育机构纷纷加强软件工程实训室的建设。软件工程实训室不仅是学生实践操作的场所...
- MES基础与应用--教案
-
教案(首页)...
- 第二章:产品入门(5) - 产品经理常用软件
-
5、产品经理常用软件软件或工具只是为了表达我们诉求的一种方式,所以在不同的工作环境或个人习惯的情况下,每个人使用的方式也会不一样。通常情况下,这篇章中介绍的这些软件是产品经理工作中运用比较多的软件,但...
- Visual Paradigm使用技巧:在不同的编程语言中呈现UML类图
-
创建一个特定语言的项目在本节中,我们将向你展现如何创建一个特定语言的项目。通过以下操作你可以很容易的构建一个所指定语言类型的类模型。不要担心本节所选择的示例语言与你实际的生产项目不同。你可以随时切换语...
- ER模型怎么画?快速绘制ER模型操作方法分享
-
ER模型是什么呢?ER模型的英文全称为Entity-relationshipmodel,又称实体-联系模型、实体关系模型或实体联系模式图,是指一类概念数据模型的高层描述所使用的数据模型或模式图。简单...
- jsjiami.v7预告,在线js加密工具重大升级
-
时隔一年,jsjiami.v6即将升级v7,解密难度徒增。JS加密测试,源代码如下...
- 国产RISC-V终端Sipeed Lichee Console4A上架,1699元起
-
IT之家12月11日消息,国内著名开源硬件厂商Sipeed矽速科技推出RISC-V终端LicheeConsole4A,售价1699元(不带LM4A模块)-3299元。Li...
- H3C交换机常用配置命令
-
1、配置主机名...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
推荐7个模板代码和其他游戏源码下载的网址
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)