IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 7.SpringBoot集成任务调度Scheduler -> 正文阅读

[Java知识库]7.SpringBoot集成任务调度Scheduler

SpringBoot集成任务调度Scheduler

基础步骤

  • 第一步:引入pom依赖
    <!--支持任务调度-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
  • 第二步:开启任务调度支持
@EnableScheduling
public class RootConfig {
}
  • 第三步:自定义类
@Component
public class ScheduleJob {
    /**
     * 每间隔两秒执行一次
     * fixedDelay: 间隔时间是根据上次的任务结束的时候开始计时的
     *      2022-05-07T22:01:53.025288100----------
     *      2022-05-07T22:02:00.027980700----------
     *      2022-05-07T22:02:07.031691200----------
     * fixedRate: 间隔时间是根据上次任务开始的时候计时的   易产生线程阻塞
     *      2022-05-07T22:05:01.320040600----------
     *      2022-05-07T22:05:06.320986600----------
     *      2022-05-07T22:05:11.321895300----------
     */
//    @Scheduled(fixedDelay = 2,timeUnit = TimeUnit.SECONDS)
    @Scheduled(fixedRate = 2,timeUnit = TimeUnit.SECONDS)
    public void testSchedule() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println(LocalDateTime.now()+"----------");
    }
}

Scheduled注解

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
    //cron表达式
    String cron() default "";
	//单位默认毫秒
    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}

@Scheduled(fixedRate)如何避免任务被阻塞

加上注解@EnableAsync(类上)和@Async(方法上),加了注解以后,就开启了多线程模式,当到了下一次任务的执行时机时,如果上一次任务还没执行完,就会自动创建一个新的线程来执行它。异步执行也可以理解为保证了任务以固定速度执行。

开启多线程后,每次任务开始的间隔都是5秒钟。这是符合我们预期的,但是最后还有点缺陷,这种情况下的线程是随着任务一执行完就销毁的,等下次有需要了程序再创建一个。每次都要重新创建明显是太影响性能了,所以需要在代码里给他一个线程池。

  • 创建线程池
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(5);
        return taskScheduler;
    }

解决线程阻塞问题

@Component
@EnableAsync
public class ScheduleJob {
    
    @Scheduled(fixedRate = 2,timeUnit = TimeUnit.SECONDS)
    @Async
    public void testSchedule() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println(LocalDateTime.now()+"----------");
    }
}

执行结果如下

2022-05-07T22:20:48.117983200----------
2022-05-07T22:20:50.072179500----------
2022-05-07T22:20:52.067858600----------
2022-05-07T22:20:54.067964400----------
2022-05-07T22:20:56.067006800----------

fixedRate和fixedDelay的区别:

fixedDelay非常好理解,它的间隔时间是根据上次的任务结束的时候开始计时的。比如一个方法上设置了fixedDelay=5*1000,那么当该方法某一次执行结束后,开始计算时间,当时间达到5秒,就开始再次执行该方法。

fixedRate理解起来比较麻烦,它的间隔时间是根据上次任务开始的时候计时的。比如当方法上设置了fiexdRate=51000,该执行该方法所花的时间是2秒,那么3秒后就会再次执行该方法。
但是这里有个坑,当任务执行时长超过设置的间隔时长,那会是什么结果呢。打个比方,比如一个任务本来只需要花2秒就能执行完成,我所设置的fixedRate=5
1000,但是因为网络问题导致这个任务花了7秒才执行完成。当任务开始时Spring就会给这个任务计时,5秒钟时候Spring就会再次调用这个任务,可是发现原来的任务还在执行,这个时候第二个任务就阻塞了(这里只考虑单线程的情况下),甚至如果第一个任务花费的时间过长,还可能会使第三第四个任务被阻塞。被阻塞的任务就像排队的人一样,一旦前一个任务没了,它就立马执行。

cron表达式

通配符

单位符号支持
, - * /
, - * /
, - * /
, - * / L W
, - * /
星期/周, - * / L # 只有 # 代表 周, 其他代表 星期

, :表示枚举,例如1,2,3

-:标识连续,例如3-5

*: 表示 每一秒、分…

/:表示 间隔 , 例如 1/3从1秒开始每间隔3秒

L:表示最后, 例如 L

W:指定日最接近的工作日, 例如 2W

#: 指定第几周的星期几,例如 3#2
只有 # 代表 周, 其他代表 星期

?:日 或 星期 中 可以使用 ,表示 不指定

    /**
     * 该任务在5月的 每一天 22点  每一分的   1,2,3秒时执行
     * 秒   分   时  日   月   星期/周
     * @throws InterruptedException
     */
    @Scheduled(cron = "1,2,3 * 22 * 5 ?")
    public void testSchedule2() throws InterruptedException {
        System.err.println(LocalDateTime.now()+"===========");
    }

多线程

    /**
     * 多线程   每秒执行一次任务
     * @throws InterruptedException
     */
    @Scheduled(cron = "* * * * * ?")
    public void testSchedule3() throws InterruptedException {
        System.err.println(Thread.currentThread()+"-"+LocalDateTime.now()+"\\\\\\\\");
    }
  • yml创建线程池数量
spring:
  task:
    scheduling:
      pool:
        size: 5

官方参考文档

https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#scheduling-annotation-support

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-19 11:51:57  更:2022-05-19 11:52:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/31 13:51:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码