@Scheduled任务调度/定时任务-非分布式

1、功能概述

任务调度就是在规定的时间内执行的任务或者按照固定的频率执行的任务。是非常常见的功能之一。常见的有JDK原生的Timer, ScheduledThreadPoolExecutor以及springboot提供的@Schduled。分布式调度框架如QuartZ、Elasticjob、XXL-JOB、SchedulerX、PowerJob等。

本文主要讲解非分布式环境下的@Scheduled任务调度讲解,以及@Scheduled结合多线程和@Async异步任务的使用。

当然在任务不是很多的情况下@Scheduled也可以结合如Redis的锁机制实现分布式的任务调度,但是还是建议在分布式环境下,使用分布式调度框架如:QuartZ、Elasticjob、XXL-JOB、SchedulerX、PowerJob等。

2、@Scheduled基本使用

2.1、创建springboot工程引入包信息

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.6</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.txc</groupId><artifactId>scheduleddemo</artifactId><version>0.0.1-SNAPSHOT</version><name>scheduleddemo</name><description>scheduleddemo</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><image><builder>paketobuildpacks/builder-jammy-base:latest</builder></image><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

2.2、按照固定间隔执行

fixedDelay:按照固定间隔执行,上一个任务的结束到下一个任务的开始间隔。

initialDealay:延迟启动,启动之后指定时间再执行调度任务

@EnableScheduling:开启任务调度,写在类上只开启当前类中的任务调度,如果写在启动类上则开启项目中的所有任务调度。

@Slf4j
//加载类型开启类中,加载启动类上,开启整个项目
@EnableScheduling //是否开启
@Component
public class MyScheduled {@Scheduled(fixedDelay = 3000,initialDelay = 3000)public void process(){log.info("=====process执行========"+ LocalDateTime.now());}
}

结果分析:

从输出结果中可以看出,程序每隔3s执行一次

2.3、按照固定频率执行任务

说明1fixedRate:按照固定频率执行任务,如每三秒执行一次,上一个任务下次任务的开始,由于此时是单线程,下一个任务开始需要等上一个任务结束。

说明2:我们通过Thread.sleep(5000)设置任务执行需要2s时间

@Slf4j
//加载类型开启类中,加载启动类上,开启整个项目
@EnableScheduling //是否开启
@Component
public class MyScheduled {
@Scheduled(fixedRate = 3000,initialDelay = 3000)
public void process() throws InterruptedException {
log.info("=====process执行fixedRate开始========"+ LocalDateTime.now());Thread.sleep(2000);log.info("=====process执行fixedRate结束========"+ LocalDateTime.now());}
}

结果分析:
从结果中可以看出由于设置process执行的时间为2s钟,process按照固定的频率(3s)3s执行一次,第一次开始是22:19:22,第二次开始是22:19:25

2.4、按照固定频率执行任务

说明1fixedRate:按照固定频率执行任务,如每三秒执行一次,上一个任务下次任务的开始,由于此时是单线程,下一个任务开始需要等上一个任务结束。

说明2:我们通过Thread.sleep(5000)设置任务执行需要5s时间

@Slf4j
//加载类型开启类中,加载启动类上,开启整个项目
@EnableScheduling //是否开启
@Component
public class MyScheduled {
@Scheduled(fixedRate = 3000,initialDelay = 3000)
public void process() throws InterruptedException {log.info("=====process执行fixedRate开始========"+ LocalDateTime.now());Thread.sleep(5000);log.info("=====process执行fixedRate结束========"+ LocalDateTime.now());}
}

结果分析:

从结果可以看出:虽然设置固定的频率是3s,但是由于在单线程情况下下次任务的开启需要等待上一个任务的结束,第一次任务开始时间为22:17:43,第二次任务开启时间为22:17:48中间间隔了5s钟。

2.5、通过公式设置定时任务

cron:可以通过特性的公式设定定时任务,任务生成网站https://cron.qqe2.com/

如:可以设置每周三下午五点执行,每月的月尾执行一次等。

如上图生成的语法表示:每分钟的前五秒执行process

@Slf4j
//加载类型开启类中,加载启动类上,开启整个项目
@EnableScheduling //是否开启
@Component
public class MyScheduled {
@Scheduled(cron ="0,1,2,3,4 * * * * ? ")
public void process() throws InterruptedException {log.info("=====process执行fixedRate开始========"+ LocalDateTime.now());Thread.sleep(5000);log.info("=====process执行fixedRate结束========"+ LocalDateTime.now());}
}

结果分析:

从图中可以看出每每分钟开始的时候执行,五秒后结束。

3、@Scheduled与多线程

加入多线程的目的是为了程序执行的效率能够提高。但是在设置多线程的时候,不能开辟过多的线程,因为线程资源非常的消耗cpu资源,必要的时候需要使用分布式任务调度。

3.1、非多线程的情况

理论上当process1结束的时候,下次process1启动的时候需要等待process2执行结束,否则1不能启动,应该这个时候依旧是单线程。

@Slf4j
//加载类型开启类中,加载启动类上,开启整个项目
@EnableScheduling //是否开启
@Component
public class MyScheduled {
@Scheduled(fixedDelay = 3000)
public void process1() throws InterruptedException {
log.info("=====process1执行开始========"+ LocalDateTime.now());Thread.sleep(5000);log.info("=====process1执行结束========"+ LocalDateTime.now());}
@Scheduled(fixedDelay = 3000)
public void process2() throws InterruptedException {log.info("=====process2执行开始========"+ LocalDateTime.now());Thread.sleep(5000);log.info("=====process2执行结束========"+ LocalDateTime.now());}
}

结果分析:

从输出结果可以看出process2的开始是等到process1结束后才执行的。

3.2、多线程的情况

在启动类中定义线程池。值不需要设置太大,现成对cpu资源消耗大,搞不好容易让系统宕机。

设置多线程后直接启动程序,继续观看process1和process2的输出情况。

package com.txc.scheduleddemo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;@SpringBootApplication
public class ScheduleddemoApplication {public static void main(String[] args) {SpringApplication.run(ScheduleddemoApplication.class, args);}@Beanpublic TaskScheduler taskScheduler(){ThreadPoolTaskScheduler taskScheduler=new ThreadPoolTaskScheduler();//设置线程池中线程的数量//多线程对cpu资源消耗较大,值不能太大。taskScheduler.setPoolSize(5);return taskScheduler;}}

结果分析:

process1和process2使用的是不同的线程,一个线程为taskSheduler-1,一个线程为taskSheduler-2。

而且process1和process2是同时启动的,没有出现相互等待的情况,因为现在使用的是多线程的情况。

4、@Scheduled与@ Async异步任务

在上面的案例中虽然process1和process2同时执行了,没有出现相互等待的情况。但是第二次process1和process2执行依旧是等待程序5s结束后再等待3是执行。

name如何能够实现即使process1执行时间为5s,但是下一次process1的启动依旧是3s后。而不是当前的8是后。这就可以使用异步任务@Async。当然复杂的异步任务还是建议使用如MQ技术。

注意点:@Async的使用需要写在单独的一个类中,不能与当前调用业务写在一起,否则不生效。

完全不会使用@Async看如下博客:

https://blog.csdn.net/tangshiyilang/article/details/129440283

4.1、创建异步任务类及异步方法

@Component
public class AsyncTaskScheduled {@Async//那个方法需要使用异步调用,就使用该注解public void asyncMethod() {try{Thread.sleep(6000);//模拟异步执行业务的时间}catch (Exception e){System.out.println(e.getStackTrace());}}
}

4.2、需要再启动类上开启异步任务

@EnableAsync:开启异步任务调度

@SpringBootApplication
@EnableAsync
public class ScheduleddemoApplication {public static void main(String[] args) {SpringApplication.run(ScheduleddemoApplication.class, args);}@Beanpublic TaskScheduler taskScheduler(){ThreadPoolTaskScheduler taskScheduler=new ThreadPoolTaskScheduler();//设置线程池中线程的数量//多线程对cpu资源消耗较大,值不能太大。taskScheduler.setPoolSize(10);return taskScheduler;}}

4.3、创建process3和process4方法

process3和process3与之前的process1和process2方法一样都是基于多线程操作。

@Slf4j
//加载类型开启类中,加载启动类上,开启整个项目
@EnableScheduling //是否开启
@Component
public class MyScheduled {
@Autowired
AsyncTaskScheduled asyncTaskScheduled;
@Scheduled(fixedDelay = 3000)
public void process3() throws InterruptedException {
log.info("=====process3执行开始========"+ LocalDateTime.now());asyncTaskScheduled.asyncMethod();log.info("=====process3执行结束========"+ LocalDateTime.now());}
@Scheduled(fixedDelay = 3000)
public void process4() throws InterruptedException {log.info("=====process4执行开始========"+ LocalDateTime.now());asyncTaskScheduled.asyncMethod();log.info("=====process4执行结束========"+ LocalDateTime.now());}
}

结果分析:

从结果可以看出,虽然异步任务执行的时间为6s,但是process4第一次开始和第二次开始的时间间隔为3s.

5、源码下载

https://download.csdn.net/download/tangshiyilang/88627612

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

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

相关文章

MySQL之DQL语句

文章目录 DQL语句指定查询查询全部查询部分数据别名查询使用order by子句拼接查询去重查询WHERE – 条件过滤模糊查询JOIN – 多表关联求和查询排序查询统计查询分页查询 DQL语句 DQL&#xff08;Data Query Language&#xff09;查询数据 操作查询&#xff1a;select简单的查…

Cell Systems | 深度学习开启蛋白质设计新时代

今天为大家介绍的是来自Bruno Correia团队的一篇综述。深度学习领域的迅速进步对蛋白质设计产生了显著影响。最近&#xff0c;深度学习方法在蛋白质结构预测方面取得了重大突破&#xff0c;使我们能够得到数百万种蛋白质的高质量模型。结合用于生成建模和序列分析的新型架构&am…

OpenCV开发:MacOS源码编译opencv,生成支持java、python、c++各版本依赖库

OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它为开发者提供了丰富的工具和函数&#xff0c;用于处理图像和视频数据&#xff0c;以及执行各种计算机视觉任务。 以下是 OpenCV 的一些主要特点和功能&#xff…

二、如何保证架构的质量、架构前期准备、技术填补与崩溃预防、系统重构

1、如何保证架构的质量 -- 稳定性和健壮性 2、正确的选择是良好的开端 -- 架构前期准备 ① 架构师分类&#xff1a;系统架构师、应用架构师、业务架构师 3、技术填补与崩溃预防 4、系统重构

day39算法训练|动态规划part02

62.不同路径 代码随想录 按照动规五部曲来分析&#xff1a; 1确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] &#xff1a;表示从&#xff08;0 &#xff0c;0&#xff09;出发&#xff0c;到(i, j) 有dp[i][j]条不同的路径。 2确定递推公式 想要求…

TCP对数据的拆分

应用程序的数据一般都比较大&#xff0c;因此TCP会按照网络包的大小对数据进行拆分。 当发送缓冲区中的数据超过MSS的长度&#xff0c;数据会被以MSS长度为单位进行拆分&#xff0c;拆分出来的数据块被放进单独的网路包中。 根据发送缓冲区中的数据拆分情况&#xff0c;当判断…

基于Java SSM框架实现水果销售网站系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现水果销售网站系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&a…

【教学类-06-16】20231213 (按比例抽题+乱序or先加再减后乘)X-Y之间“加法减法乘法+-×混合题”

作品展示&#xff1a; 背景需求&#xff1a; 大三班的“第一高手”对我提供的每一套的题目都只有一种反应&#xff1a; “这个是分合题&#xff0c;太简单了” “乘法&#xff0c;乘法我也会&#xff0c;11的1 22的4 33的9&#xff0c;,44十六……” “都太简单了&#xff0…

基于linux系统的Tomcat+Mysql+Jdk环境搭建(三)centos7 安装Tomcat

Tomcat下载官网&#xff1a; Apache Tomcat - Which Version Do I Want? JDK下载官网&#xff1a; Java Downloads | Oracle 中国 如果不知道Tomcat的哪个版本应该对应哪个版本的JDK可以打开官网&#xff0c;点击Whitch Version 下滑&#xff0c;有低版本的&#xff0c;如…

设计模式(3)--对象结构(3)--组合

1. 意图 将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 2. 三种角色 抽象组件(Component)、组合式节点(Composite)、叶节点(Leaf) 3. 优点 3.1 定义了包含基本对象和组合对象的类层次结构。 客户代码中&…

C++相关闲碎记录(14)

1、数值算法 &#xff08;1&#xff09;运算后产生结果accumulate() #include "algostuff.hpp"using namespace std;int main() {vector<int> coll;INSERT_ELEMENTS(coll, 1, 9);PRINT_ELEMENTS(coll);cout << "sum: " << accumulate(…

Spring入门

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

鸿蒙ArkTS Web组件加载空白的问题原因及解决方案

问题症状 初学鸿蒙开发&#xff0c;按照官方文档Web组件文档《使用Web组件加载页面》示例中的代码照抄运行后显示空白&#xff0c;纠结之余多方搜索后扔无解决方法。 运行代码 import web_webview from ohos.web.webviewEntry Component struct Index {controller: web_webv…

docker入门小结

docker是什么&#xff1f;它有什么优势&#xff1f; 快速获取开箱即用的程序 docker使得所有的应用传输就像我们日常通过聊天工具文件传输一样&#xff0c;发送方将程序传输到超级码头而接收方也只需通过超级码头进行获取即可&#xff0c;就像一只鲸鱼拖着货物来回运输一样。…

使用java获取nvidia显卡信息

前言 AI开发通常使用到GPU&#xff0c;但通常使用的是python、c等语言&#xff0c;java用的则非常少。这也导致了java在gpu相关的库比较少。现在的需求是要获取nvidia显卡的使用情况&#xff0c;如剩余显存。这里给出两种较简单的解决方案。 基于nivdia-smi工具 显卡是硬件&a…

AMD 自适应和嵌入式产品技术日

概要 时间&#xff1a;2023年11月28日 地点&#xff1a;北京朝阳新云南皇冠假日酒店 主题内容&#xff1a;AMD自适应和嵌入式产品的更新&#xff0c;跨越 云、边、端的AI解决方案&#xff0c;赋能智能制造的机器视觉与机器人等热门话题。 注&#xff1a;本文重点关注FPGA&a…

【51单片机系列】直流电机使用

本文是关于直流电机使用的相关介绍。 文章目录 一、直流电机介绍二、ULN2003芯片介绍三、在proteus中仿真实现对电机的驱动 51单片机的应用中&#xff0c;电机控制方面的应用也很多。在学习直流电机(PWM)之前&#xff0c;先使用GPIO控制电机的正反转和停止。但不能直接使用GPIO…

textarea 网页文本框在光标处添加内容

在前端研发中我们经常需要使用脚本在文本框中插入内容。如果产品要求不能直接插入开始或者尾部&#xff0c;而是要插入到光标位置&#xff0c;此时我们就需要获取光标/光标选中的位置。 很多时候&#xff0c;我在格式化文本处需要选择选项&#xff0c;将选择的信息输入到光标位…

关于“Python”的核心知识点整理大全25

目录 10.3.4 else 代码块、 10.3.5 处理 FileNotFoundError 异常 alice.py 在这个示例中&#xff0c;try代码块引发FileNotFoundError异常&#xff0c;因此Python找出与该错误匹配的 except代码块&#xff0c;并运行其中的代码。最终的结果是显示一条友好的错误消息&#x…

基于循环神经网络长短时记忆(RNN-LSTM)的大豆土壤水分预测模型的建立

Development of a Soil Moisture Prediction Model Based on Recurrent Neural Network Long Short-Term Memory in Soybean Cultivation 1、介绍2、方法2.1 数据获取2.2.用于预测土壤湿度的 LSTM 模型2.3.土壤水分预测的RNN-LSTM模型的建立条件2.4.预测土壤水分的RNN-LSTM模型…