@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);
    }

    @Bean
    public 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);
    }

    @Bean
    public 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

出现 ‘mvn‘ 不是内部或外部命令,也不是可运行的程序或批处理文件 的解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 下载了Maven,也配置了环境,在环境变量中配置MAVEN_HOME,在用户变量中配置了bin变量 具体如下所示: 用户变量的配置: 结果显示如下所示: 2. 原理分析 HOME变量中会具体到jre变量,如果在用户变量中配置,jre可能…

SpringBoot+Vue3前后端快速整合入门

前言 最近需要维护一个个人项目&#xff0c;由于笔者是一个大后端&#xff0c;所以借此机会把前端学习过程记录一下&#xff0c;方便后续回顾。 前端项目初始化 安装npm 在前端项目初始化时&#xff0c;我们必须要安装好node&#xff0c;官网地址如下&#xff0c;因为笔者后…

数据结构实验任务八:排序算法的实现与分析

问题描述 统计成绩&#xff1a;给出 n 个学生的考试成绩表&#xff0c;每条信息由姓名和分数组成&#xff0c;试设 计一个算法&#xff1a; 1.按分数高低次序&#xff0c;打印出每个学生在考试中获得的名次&#xff0c;分数相同的为同 一名次&#xff1b; 2.按名次列出每个学生…

36V/48V转12V 10A直流降压DC-DC芯片-AH1007

AH1007是一款36V/48V转12V 10A直流降压&#xff08;DC-DC&#xff09;芯片&#xff0c;它是一种高性能的降压变换器&#xff0c;常用于工业、汽车和电子设备等领域。 AH1007采用了先进的PWM调制技术和开关电源控制算法&#xff0c;能够高效地将输入电压从36V/48V降低到12V&…

【Spark精讲】Spark内存管理

目录 前言 Java内存管理 Java运行时数据区 Java堆 垃圾回收机制 Executor内存管理 内存类型 堆内内存 堆外内存 内存管理模式 静态内存管理 统一内存管理 ​编辑 执行内存管理 多任务间内存分配 Shuffle 的内存占用 MemoryOverHead详解 任务内存调节 错误类型…

TCP/IP 四层体系结构

目录 ​编辑 导言&#xff1a; 应用层 1. HTTP&#xff08;超文本传输协议&#xff09; 2. FTP&#xff08;文件传输协议&#xff09; 3. SMTP&#xff08;简单邮件传输协议&#xff09; 4. POP3&#xff08;邮局协议第3版&#xff09; 5. IMAP&#xff08;互联网消息访…

群晖(Synology)新建存储池使用 Home 服务

每一个用户都可以有一个自己的 Home 服务。 这个在群晖存储新建存储池后可以自动启用这个服务。 启用后&#xff0c;可以看到你的文件系统中有一个 homes 的文件了。 群晖&#xff08;Synology&#xff09;新建存储池使用 Home 服务 - 系统容器 - iSharkFly每一个用户都可以有…

尚硅谷JavaWeb电子书城项目(Java+Mysql+Tomcat+Jsp)

自己写的在线电子书城项目&#xff0c;可改写&#xff0c;添加功能&#xff0c;如打折&#xff0c;分类&#xff0c;用户管理&#xff0c;评论等功能。 使用方法&#xff1a; 1.使用idea导入项目。 2.数据库要用项目resource文件里的book.sql文件建立。 3.修改jdbc.properi…

【从零开始学习JVM | 第八篇】学习垃圾回收算法 和 垃圾回收器

前言&#xff1a; 现代编程语言通常采用垃圾回收机制来自动管理内存。垃圾回收机制是一种自动化的内存管理技术&#xff0c;可以在程序运行时自动识别和回收不再使用的内存&#xff0c;从而减少内存泄漏和其他内存相关问题的发生。 本文将介绍垃圾回收算法和垃圾回收器的相关…

【产品】Axure的基本使用(二)

文章目录 一、元件基本介绍1.1 概述1.2 元件操作1.3 热区的使用 二、表单型元件的使用2.1 文本框2.2 文本域2.3 下拉列表2.4 列表框2.5 单选按钮2.6 复选框2.7 菜单与表格元件的使用 三、实例3.1 登录2.2 个人简历 一、元件基本介绍 1.1 概述 在Axure RP中&#xff0c;元件是…

模块四(一):搭建自己的SSR

前言&#xff1a;同构渲染是将服务器渲染和客户端渲染相结合的一种渲染方式&#xff0c;在服务端生成初始页面&#xff0c;提升首屏加载速度&#xff0c;并且有利于SEO&#xff1b;在客户端接管HTML&#xff0c;并且将静态HTML激活为数据绑定的动态HTML&#xff0c;为用户提供更…

算法通关村第五关—LRU的设计与实现(黄金)

LRU的设计与实现 一、理解LRU的原理 LeetCode146:运用你所掌握的数据结构&#xff0c;设计和实现一个LRU(最近最少使用)缓存机制 实现LRUCache类&#xff1a; LRUCache(int capacity) 以正整数作为容量capacity初始化 LRU 缓存 int get(int key) 如果关键字key存在于缓存中&a…

节流防抖:提升前端性能的秘密武器(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

小程序开发实战案例之三 | 小程序底部导航栏如何设置

小程序中最常见的功能就是底部导航栏了&#xff0c;今天就来看一下怎么设置一个好看的导航栏&#xff5e;这里我们使用的是支付宝官方小程序 IDE 做示范。 官方提供的底部导航栏 第一步&#xff1a;页面创建 一般的小程序会有四个 tab&#xff0c;我们这次也是配置四个 tab 的…

学习深度强化学习---第3部分----RL蒙特卡罗相关算法

文章目录 3.1节 蒙特卡罗法简介3.2节 蒙特卡罗策略评估3.3节 蒙特卡罗强化学习3.4节 异策略蒙特卡罗法 本部分视频所在地址&#xff1a;深度强化学习的理论与实践 3.1节 蒙特卡罗法简介 在其他学科中的蒙特卡罗法是一种抽样的方法。 如果状态转移概率是已知的&#xff0c;则是…

FMETP STREAM 2.0

FMETPSTREAM简化了Unity3D中的直播,无需编码。设置和测试仅需5分钟。 "编码器模块"将Unity游戏视图、网络摄像头、桌面、声音和麦克风输入转换为字节数据,使其完美适用于各种流媒体场景。 优化的网络模块支持Server-clients连接类型,并允许您使用单个命令向 Serve…

Facebook的DINO,无监督模型,可用于分类和分割任务

Facebook的DINO 参考&#xff1a;https://blog.csdn.net/hello_dear_you/article/details/133695006 代码&#xff1a;https://github.com/facebookresearch/dino/tree/main DINO本质上是一种自监督学习方法&#xff0c;其核心思想是通过在大规模的无标签数据集上进行对比学习&…

数据结构与算法:衡量算法好坏的指标——复杂度

1.复杂度 复杂度&#xff0c;用来分析算法执行过程中&#xff0c;所需要的资源。 时间复杂度是衡量所需要的时间。 空间复杂度&#xff0c;是衡量所需要的(内存)空间。 1.1 时间复杂度 特性 1.衡量算法执行所需时间 2.根据「常数操作」次数推定 3.一般以最大数据量N作为衡量…

关于标准库中的list(涉及STL的精华-迭代器的底层)

目录 关于list list常见接口实现 STL的精华之迭代器 关于list list的文档介绍 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2. list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立…

解析视频美颜SDK的算法:美肤、滤镜与实时处理

如今&#xff0c;美颜技术在视频处理中扮演着关键的角色&#xff0c;为用户提供更加精致的视觉体验。本文将深入探讨视频美颜SDK的算法&#xff0c;聚焦于美肤、滤镜与实时处理等方面&#xff0c;揭示背后的科技奥秘。 一、美肤算法的魅力 视频美颜的一个核心功能就是美肤&am…