玩转SpringBoot之定时任务详解

 

玩转SpringBoot之定时任务详解

 

 

https://www.cnblogs.com/mmzs/p/10161936.html

 

玩转SpringBoot之定时任务详解

阅读目录:

  • 序言
  • 一、静态:基于注解
  • 二、动态:基于接口
  • 三、多线程定时任务

 

阅读正文:

回到顶部

序言

使用SpringBoot创建定时任务非常简单,目前主要有以下三种创建方式:

  • 一、基于注解(@Scheduled)
  • 二、基于接口(SchedulingConfigurer) 前者相信大家都很熟悉,但是实际使用中我们往往想从数据库中读取指定时间来动态执行定时任务,这时候基于接口的定时任务就派上用场了。
  • 三、基于注解设定多线程定时任务

回到顶部

一、静态:基于注解

基于注解@Scheduled默认为单线程,开启多个任务时,任务的执行时机会受上一个任务执行时间的影响。

1、创建定时器

使用SpringBoot基于注解来创建定时任务非常简单,只需几行代码便可完成。 代码如下:

复制代码

@Configuration      //1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling   // 2.开启定时任务
public class SaticScheduleTask {//3.添加定时任务@Scheduled(cron = "0/5 * * * * ?")//或直接指定时间间隔,例如:5秒//@Scheduled(fixedRate=5000)private void configureTasks() {System.err.println("执行静态定时任务时间: " + LocalDateTime.now());}
}

复制代码

 

Cron表达式参数分别表示:

  • 秒(0~59) 例如0/5表示每5秒
  • 分(0~59)
  • 时(0~23)
  • 日(0~31)的某天,需计算
  • 月(0~11)
  • 周几( 可填1-7 或 SUN/MON/TUE/WED/THU/FRI/SAT)

@Scheduled:除了支持灵活的参数表达式cron之外,还支持简单的延时操作,例如 fixedDelay ,fixedRate 填写相应的毫秒数即可。

 

2、启动测试

启动应用,可以看到控制台打印出如下信息:

在这里插入图片描述

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

 

回到顶部

二、动态:基于接口

基于接口(SchedulingConfigurer)

1、导入依赖包:

复制代码

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.0.4.RELEASE</version></parent><dependencies><dependency><!--添加Web依赖 --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><!--添加MySql依赖 --><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><!--添加Mybatis依赖 配置mybatis的一些初始化的东西--><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.1</version></dependency><dependency><!-- 添加mybatis依赖 --><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version><scope>compile</scope></dependency></dependencies>

复制代码

 

2、添加数据库记录:

开启本地数据库mysql,随便打开查询窗口,然后执行脚本内容,如下:

复制代码

DROP DATABASE IF EXISTS `socks`;
CREATE DATABASE `socks`;
USE `SOCKS`;
DROP TABLE IF EXISTS `cron`;
CREATE TABLE `cron`  (`cron_id` varchar(30) NOT NULL PRIMARY KEY,`cron` varchar(30) NOT NULL  
);
INSERT INTO `cron` VALUES ('1', '0/5 * * * * ?');

复制代码

在这里插入图片描述

然后在项目中的application.yml 添加数据源:

spring:datasource:url: jdbc:mysql://localhost:3306/socksusername: rootpassword: 123456

 

3、创建定时器

数据库准备好数据之后,我们编写定时任务,注意这里添加的是TriggerTask,目的是循环读取我们在数据库设置好的执行周期,以及执行相关定时任务的内容。
具体代码如下:

复制代码

@Configuration      //1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling   // 2.开启定时任务
public class DynamicScheduleTask implements SchedulingConfigurer {@Mapperpublic interface CronMapper {@Select("select cron from cron limit 1")public String getCron();}@Autowired      //注入mapper@SuppressWarnings("all")CronMapper cronMapper;/*** 执行定时任务.*/@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.addTriggerTask(//1.添加任务内容(Runnable)() -> System.out.println("执行动态定时任务: " + LocalDateTime.now().toLocalTime()),//2.设置执行周期(Trigger)triggerContext -> {//2.1 从数据库获取执行周期String cron = cronMapper.getCron();//2.2 合法性校验.if (StringUtils.isEmpty(cron)) {// Omitted Code ..}//2.3 返回执行周期(Date)return new CronTrigger(cron).nextExecutionTime(triggerContext);});}}

复制代码

 

4、启动测试

启动应用后,查看控制台,打印时间是我们预期的每10秒一次:
在这里插入图片描述

然后打开Navicat ,将执行周期修改为每6秒执行一次,如图:
在这里插入图片描述

查看控制台,发现执行周期已经改变,并且不需要我们重启应用,十分方便。如图:
在这里插入图片描述

注意: 如果在数据库修改时格式出现错误,则定时任务会停止,即使重新修改正确;此时只能重新启动项目才能恢复。

 

回到顶部

三、多线程定时任务

基于注解设定多线程定时任务

1、创建多线程定时任务

复制代码

//@Component注解用于对那些比较中立的类进行注释;
//相对与在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释
@Component
@EnableScheduling   // 1.开启定时任务
@EnableAsync        // 2.开启多线程
public class MultithreadScheduleTask {@Async@Scheduled(fixedDelay = 1000)  //间隔1秒public void first() throws InterruptedException {System.out.println("第一个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());System.out.println();Thread.sleep(1000 * 10);}@Async@Scheduled(fixedDelay = 2000)public void second() {System.out.println("第二个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());System.out.println();}}

复制代码

注: 这里的@Async注解很关键

 

2、启动测试

启动应用后,查看控制台:
在这里插入图片描述

从控制台可以看出,第一个定时任务和第二个定时任务互不影响;

并且,由于开启了多线程,第一个任务的执行时间也不受其本身执行时间的限制,所以需要注意可能会出现重复操作导致数据异常。

 

代码地址:https://github.com/mmzsblog/springboot-schedule

 

原文链接:https://www.mmzsblog.cn/articles/2019/08/08/1565247960802.html

 

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327172.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java开发人员必知必会的20种常用类库和API

转载自 Java开发人员必知必会的20种常用类库和API 一个有经验的Java开发人员特征之一就是善于使用已有的轮子来造车。《Effective Java》的作者Joshua Bloch曾经说过&#xff1a;“建议使用现有的API来开发&#xff0c;而不是重复造轮子”。在本文中,我将分享一些Java开发人员应…

左耳朵耗子:不灌鸡汤,说真的年龄渐长,技术人的发展之路该怎么走

技术圈中的很多人&#xff0c;最初都坚定地认为coding能改变世界。然而三五年过去后&#xff0c;还能不忘初心的人&#xff0c;少之又少。随着年龄的增长&#xff0c;梦想已被束之高阁&#xff0c;面包慢慢占据生活的大部分。对于个人发展&#xff0c;很多成功学者会给你灌各种…

Java开发必须掌握的5种加密策略

转载自 Java开发必须掌握的5种加密策略 本文总结自《大型电商分布式系统实践——第四课》。文末给出获取全套PPT及视频的方式。 一、数字摘要 数字摘要也称为消息摘要,它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash函数对消息进行计算而产生。如果消息在传…

Java String格式日期加1秒(分钟或小时) java时间减一分钟,并且进行比较-时间相关的处理

https://blog.csdn.net/java0311/article/details/78047878 Java String格式日期加1秒&#xff08;分钟或小时&#xff09; chuan9966 2017-09-21 09:15:07 17101 收藏 6 文章标签&#xff1a; String格式日期加1秒 data日期加1秒 日期加1秒 版权 需求&#xff1a; 将如下…

聊下JVM内存模型

转载自 聊下JVM内存模型 1. JVM内存模型 2. 程序计数器(PC) 每个线程都会有自己私有的程序计数器(PC)。可以看作是当前线程所执行的字节码的行号指示器。 也可以理解为下一条将要执行的指令的地址或者行号。字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码…

泛型集合

作用 它是一个泛型类&#xff0c;而之前使用的时候并没有传递&#xff0c;说明java语法是允许的&#xff0c;这个时候传递的类型是Object类&#xff0c;虽然它是所有类的父类&#xff0c;可以存储任意的类型&#xff0c;但是在遍历、获取元素时需要原来的类型就要进行强制转换。…

ASP.NET Core + Angular 2 Template for Visual Studio

多个月以来&#xff0c;我和多个Github上的社区贡献者一起建立支持库、包&#xff0c;我们最终的目的是希望完成这样一个作为起点的模板&#xff0c;也就是基于把Typescript代码和Angular2宿主在ASP.NET Core项目中&#xff0c;这个模板包含一下这些方面&#xff1a; 服务端预加…

MyBatis中if - else if - else 的使用

http://www.leftso.com/blog/765.html 不过有他的替代 choose,写法如下&#xff1a; <choose><when test"params!null">right JOIN</when><otherwise>LEFT JOIN</otherwise></choose> 复制 <choose><when test…

C#高性能TCP服务的多种实现方式

☆ 哎~~ 想想大部分园友应该对 "高性能" 字样更感兴趣&#xff0c;为了吸引眼球所以标题中一定要突出&#xff0c;其实我更喜欢的标题是《猴赛雷&#xff0c;C#编写TCP服务的花样姿势&#xff01;》。 本篇文章的主旨是使用 .NET/C# 实现 TCP 高性能服务的不同方式&a…

mysql中 where in 用法详解

https://blog.csdn.net/haibo0668/article/details/52584307 sssss mysql中 where in 用法详解 我是高手高手高高手 2016-09-19 11:33:29 102915 收藏 14 分类专栏&#xff1a; php MY SQL &#xfeff;&#xfeff; 这里分两种情况来介绍 WHERE column IN (value1,valu…

HashSet的存储方式

存储结构 存储过程

写给新手的WebAPI实践

此篇是写给新手的Demo&#xff0c;用于参考和借鉴&#xff0c;用于发散思路。老鸟可以忽略了。 自己经常有这种情况&#xff0c;遇到一个新东西或难题&#xff0c;在了解和解决之前总是说“等搞定了一定要写篇文章记录下来”&#xff0c;但是当掌握了之后&#xff0c;就感觉好简…

用limit 实现java的简单分页

https://blog.csdn.net/xinyuezitang/article/details/84324359 用limit 实现java的简单分页 xinyuezitang 2018-11-21 16:01:13 4447 收藏 9 分类专栏&#xff1a; Java 小Demo 文章标签&#xff1a; 分页 limit mysql 实现java分页 版权 一 mysql 中limit 用法 select …

Mybatis使用IN语句查询

https://blog.csdn.net/u011781521/article/details/79669180 Mybatis使用IN语句查询 lfendo 2018-03-23 16:45:03 201525 收藏 140 分类专栏&#xff1a; MyBatis 文章标签&#xff1a; mybatis JAVA sql 版权 一、简介 在SQL语法中如果我们想使用in的话直接可以像如下一…

IdentityServer4 实现 OpenID Connect 和 OAuth 2.0

关于 OAuth 2.0 的相关内容&#xff0c;点击查看&#xff1a;ASP.NET WebApi OWIN 实现 OAuth 2.0 OpenID 是一个去中心化的网上身份认证系统。对于支持 OpenID 的网站&#xff0c;用户不需要记住像用户名和密码这样的传统验证标记。取而代之的是&#xff0c;他们只需要预先在一…

Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

转载自 Java动态代理机制详解&#xff08;JDK 和CGLIB&#xff0c;Javassist&#xff0c;ASM&#xff09; class文件简介及加载 Java编译器编译好Java文件之后&#xff0c;产生.class 文件在磁盘中。这种class文件是二进制文件&#xff0c;内容是只有JVM虚拟机能够识别的机器码…

彻底理解JAVA动态代理

转载自 彻底理解JAVA动态代理 代理设计模式 定义&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。 代理模式的结构如下图所示。 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念。 代理模式示例代码 public interface Subject { pu…

docker 安装redis 挂载到宿主机

1.首先去redis获取对应版本的配置文件redis.conf&#xff1a; http://download.redis.io/releases/ 我选择的是 6.0.9 解压以后 有一个redis.conf 2.将 bind 127.0.0.1注释&#xff0c;daemonize yes注释掉&#xff0c;如果需要redis密码则找到 requirepass 并填上你的密码 …

搭建consul 集群

上图是官网提供的一个事例系统图&#xff0c;图中的Server是consul服务端高可用集群&#xff0c;Client是consul客户端。consul客户端不保存数据&#xff0c;客户端将接收到的请求转发给响应的Server端。Server之间通过局域网或广域网通信实现数据一致性。每个Server或Client都…