SpringBoot中的定时任务@Scheduled的使用

news2024/11/6 23:23:48

1.@Scheduled注解介绍

在spring boot的项目中需要使用到定时任务的时候,可以使用@Scheduled注解,这只是在一个JVM进程中很适用,如果涉及到服务器是集群的情况下,建议使用任务调度平台。这样任务调度平台会在多台服务器中选择一台进行定时任务的执行。该注解位于spring-context.jar包中

 2.@Scheduled相关属性说明

属性说明
cron():String使用Cron表达式创建定时任务,值可以是字符串也“0 * * * * MON-FRI”可以是${...}获取配置文件中定义的表达式
zone():String指定cron的时区,默认是空字符串,表示本地时区
fixedDelay():long任务执行的时间间隔,表示第一次任务执行完毕和第二次任务开始之间的时间,单位:毫秒
fixedRate():long每隔多久执行一次任务,第一次任务开始和第二次任务开始之间的时间,单位:毫秒
initialDelay():long表示第一次执行fixedDelayfixedRate要等待的时间,单位:毫秒

3.@Scheduled简单使用

(1)首先要知道@Scheduled注解要生效需要在系统启动类或配置类上添加@EnableScheduling注解,这里在系统的启动类上加@EnableScheduling注解。如下所示:

(2)创建一个定时任务类TestSchedule,使用@Component注解标注,交给容器管理。定义一个方法taskScheduledOne,并在方法上加上注解@Scheduled以及cron表达式,如下图所示@Scheduled(cron = "0/10 * * * * ?")表示该定时任务每10秒钟执行一次。

 (3)执行效果如下:

如上图的打印效果所示, 到这里,一个简单的定时任务就已经完成了

4.可能出现的问题一:两个定时任务执行时间间隔问题

测试代码如下所示:

@Component
public class TestSchedule {

    /**
     * 每十秒钟执行一次
     */
    @Scheduled(cron = "0/10 * * * * ?")
    public void taskScheduledOne() throws InterruptedException {
        Thread t = Thread.currentThread();
        System.out.println("taskScheduledOne "+ DateTimeUtils.dateToString(new Date()) +" ThreadID:"+ t.getId() +" "+t.getName());
        Thread.sleep(5000);
        System.out.println("taskScheduledOne End " + DateTimeUtils.dateToString(new Date()) + " ThreadID:" + t.getId() + " " + t.getName());
    }

    /**
     * 每三秒钟执行一次
     */
    @Scheduled(cron = "0/3 * * * * ?")
    public void taskScheduledTwo() {
        Thread t = Thread.currentThread();
        System.out.println("taskScheduledTwo " + DateTimeUtils.dateToString(new Date()) + " ThreadID:" + t.getId() + " " + t.getName());
    }

}

运行代码,最初的部分结果打印如图所示:我们发现定时任务2和定时任务1都是一个线程(线程id为48)执行的,定时任务2是每3秒钟执行一次,但这里出现了问题,如下图中的箭头所示,定时任务2在“ 2023/06/08 20:24:39 ”执行完,下一次的执行完的时间按理说应该是“ 2023/06/08 20:24:42 ”,但结果显示时间是2023/06/08 20:24:45,说明这里出现了问题。

问题解释:因为Spring中@EnableScheduling和@Scheduled标注的定时任务默认是单线程执行的,所以定时任务2 在箭头A 执行完,定时任务1开始执行,定时任务1 和 定时任务2 都是同一个线程执行的,这里的定时任务1执行花费5s左右的时间,已经超过了定时任务2的3s执行周期,导致定时任务2被阻塞了。所以定时任务2再执行打印时,就出现在箭头B这个地方了,时间差已经超过了3s。

 5.可能出现的问题二:使用@Async和@EnableAsync异步执行任务

 Spring的定时任务包中提供了@EnableAsync和@Async注解用于多线程异步执行任务。

在启动类上添加@EnableAsync注解,并在TestSchedule类上标注@Async注解,表示该类中所有标注了@Scheduled的方法都使用异步处理方式。

 

 再次执行之前的代码看一下效果:

定时任务2时间间隔均是3s,定时任务1时间间隔也是10s,且非单线程操作了。

 这里看似解决了上述问题一,但其实可能会引入第二个问题,就是定时任务的执行时间过长,超过定时任务执行的周期。修改一下上述的代码,将定时任务1线程沉睡的时间由5s改为11s。再次执行代码:

Thread.sleep(5000);
// 改为
Thread.sleep(11000);

执行效果如下:定时任务2正常执行。但定时任务1执行出现了线程交叉执行。

原因解释:定时任务1的执行时间超过了定时任务的执行周期,在某个线程执行定时任务1时,还没结束,下一个线程又开始执行定时任务1了,这就是使用@EnableAsync和@Async异步执行定时任务可能会出现的问题。

 

 6.问题一和问题二的解决方案

(1)去掉如下注释的注解

 

 (2)创建一个任务配置类ScheduleConfig 实现SchedulingConfigurer接口的configureTasks方法,使用参数taskRegistrar为任务调度创建线程池;

@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean(destroyMethod = "shutdown")
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(10);
    }
    
}

运行结果如下图所示:定时任务2执行正常,定时任务1执行也正常,不会出现交叉现象,定时任务1第二次执行的时间会等第一次执行完毕之后下一个任务任务调度时间点开始才会执行。

 

 7.总结

SpringBoot中可以使用@EnableScheduling和@Scheduled注解实现定时任务调度,但是注意默认所有任务都被单个线程调度的,有可能任务之间发生阻塞现象,可以使用@EnableAsync和@Async注解实现异步多线程任务调度,但需要注意任务执行时间如果大于任务调度周期时间,可能出现同一个任务交叉执行的情况。上述6可以解决相关问题。

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

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

相关文章

【linux】在Ubuntu下部署nginx——nginx的安装与卸载

介绍 这里是小编成长之路的历程,也是小编的学习之路。希望和各位大佬们一起成长! 以下为小编最喜欢的两句话: 要有最朴素的生活和最遥远的梦想,即使明天天寒地冻,山高水远,路远马亡。 一个人为什么要努力&a…

Think PHP6+Swagger3

swagger是一个解决接口规范化、标准化、文档化的一个组件,既可以直接自动生成resutful接口文档又能进行功能测试的一个web服务。本文是think PHP6结合swagger3的一个记录过程。 composer安装ThinkPHP 一般安装最新稳定版本,不一定是最新版本 composer…

怎么通过Fiddler对APP进行抓包?以及高级应用场景分析

目录 前言 简单说下Fiddler的抓包原理: 使用fiddler代理远程捕获APP请求 Fiddler高级应用场景介绍 1、url地址重写 fiddler抓包详细教程:全网抓包天花板教程,B站讲的最详细的Fiddler/Charles抓包教学视频。2小时包你学会_哔哩哔哩_bilibi…

软件测试之路已不再是坦途

去年下半年才跳了槽,过程非常顺利,没有经历大家所说的工作荒的境地,所以一直没有直观地感受到软件测试就业形势到底有多严峻。 近来看到一些机构频频发出某某测试员在糟糕的就业形势下逆袭拿下XXW的某厂offer,然后推荐测试进阶课…

Django学习笔记-配置Docker、Git环境与项目创建

笔记内容转载自AcWing的Django框架课讲义,课程链接:AcWing Django框架课。 CONTENTS 1. 配置Docker环境2. Django项目创建3. Django App创建 1. 配置Docker环境 首先拉取一个 Ubuntu 镜像: docker pull ubuntu:20.04创建容器后进入容器配置…

Splunk:构建安全监控解决方案(第 1 部分)

在我的网络安全训练营的最后几周,我们的最终项目之一是使用 Splunk Enterprise 为一个名为 VSI(虚拟空间工业)的虚构组织构建安全监控环境,对于那些可能不知道的人来说,它是一个 SIEM(安全信息和事件管理器…

科一容易忘、容易混的点——图类

注意行人 和 人行横道区别 注意行人:黄色,里面是什么就注意什么 人行横道:正方形 “不得” xxx 的 就选择 【正确】 点火开关 1、LOCK档:这是一个锁止档,功能是当除了防盗系统和车内小灯以外,电路是完全关…

【Redis应用】用户签到统计连续签到(三)

🚗Redis应用学习第三站~ 🚩本文已收录至专栏:Redis技术学习 签到功能是我们非常常见的一个功能,几乎在每个app中都能碰到,让我们一起看看如何实现吧~ 一.BitMap用法引入 我们针对签到功能完全可以通过mysql来完成&am…

Python基于指定范围筛选并剔除Excel表格中的数据

本文介绍基于Python语言,读取Excel表格文件,基于我们给定的规则,对其中的数据加以筛选,将不在指定数据范围内的数据剔除,保留符合我们需要的数据的方法。 首先,我们来明确一下本文的具体需求。现有一个Exce…

【JavaScript】讲解JavaScript的基础知识并且配有案例讲解

🎊专栏【 前端易错合集】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【如愿】 大一同学小吉,欢迎并且感谢大家指出我的问题🥰 目录 🎁JavaScript嵌入网页的方式 🍔a…

LVS--DR集群部署

LVS--DR集群 一、DR模式原理二、实验 一、DR模式原理 原理:首先负载均衡器接收到客户的请求数据包时,根据调度算法决定将请求发送给哪个后端的真实服务器(RS)。然后负载均衡器就把客户端发送的请求数据包的目标MAC地址改成后端真…

PCI Express架构概述

目录 1. PCIe 总线概述 2. PCIe 拓扑结构 3. PCIe 分层结构 4. PCIe 事务层类型 5. PCIe 配置和地址空间 1. PCIe 总线概述 PCIe(Peripheral Component Interconnect Express)是一种用于连接计算机内部硬件设备的高速串行总线。它是在PCI&#xff08…

在Windows 11 中安装和使用 WSL 2

文章目录 列出可安装的发行版/分发安装WSL 2常用命令显示帮助启动分发从powershell中退出分发关闭正在运行的分发立即终止所有正在运行的分发和 WSL 2轻型虚拟机。更新wsl 使用VSCode连接WSL设置代理换源WSL 与 Windows 11 共享文件导入、导出 WSL 发行版导出导入 安装Docker E…

Nacos架构与原理 - 总体架构

文章目录 Nacos 起源Nacos 定位Nacos 优势Nacos 生态Nacos 总体设计设计原则架构图用户层业务层内核层插件 小结 Nacos 起源 Nacos 在阿里巴巴起源于 2008 年五彩石项目(完成微服务拆分和业务中台建设),成长于十年双十⼀的洪峰考验&#xff…

【大数据之路1】Hadoop 入门

1. Hadoop 入门 1. 大数据概述1. 大数据相关说明2. Hadoop 及大数据生态圈3. Hadoop 核心组件4. Hadoop 生态圈5. 集群安装模式6. Hadoop 运行模式7. Hadoop 工作流程8. Hadoop 的推行策略9. 知识点 2. Hadoop 启动与服务名1. Hadoop(HDFS/YARN)启动2. H…

区间预测 | MATLAB实现基于QRCNN-BiGRU卷积双向门控循环单元多变量时间序列区间预测

区间预测 | MATLAB实现基于QRCNN-BiGRU卷积双向门控循环单元多变量时间序列区间预测 目录 区间预测 | MATLAB实现基于QRCNN-BiGRU卷积双向门控循环单元多变量时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于QRCNN-BiGRU卷积神经…

数据结构4:二叉树

目录 1.树概念及结构 1.1树的概念 1.3树的表示 1.4树在实际中的运用(表示文件系统的目录结构) 2.二叉树的概念及结构 2.1概念 2.2现实中的二叉树: 2.3特殊的二叉树: 2.4 二叉树的性质 2.5二叉树的存储结构 1.顺序结构 …

如何用 10 种策略改进 ChatGPT 的人工智能

你是否曾有过和AI机器人交互无果的经历?或许只是因为提示语的问题!想要ChatGPT/Bard/Bing Chat等AI机器人更智能、回应更高效? 必须学会AI提示语技巧!本文将深入解析如何用精准的语言编写提示,让您的AI聊天机器人更进一步。 为什…

从买卖股票入手谈谈DP Table

动态规划问题主要就是要明确dp函数定义、搞清楚状态以及状态转移方程 构建DP思路解析 状态 188. 买卖股票的最佳时机 IV - 力扣(LeetCode) 对于股票,我们每天有三种选择 > buy, sell, hold 限制条件有 > 天数限制(n&…

Java关键字abstract详解

abstract 1.可以用来修饰:类、方法 2.具体的: abstract修饰类:抽象类 抽象类不能实例化 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)。 开发中,都会提…