Spring多定时任务@Scheduled执行阻塞问题

2023-11-03

一. 问题描述
  最近项目中发现一个问题,计划每日凌晨4:40执行一个定时任务,使用注解方式: @Scheduled(cron = “0 40 4 * * ?”),cron表达式明显没有问题,但是这个定时任务总是不按时执行,有时候得等到8点多,有时候9点多才执行。后来查了下,原来这种定时方式默认是单线程执行的,恰好我这里有多个定时任务,并且其中有个在4:40之前的定时任务比较耗时,导致4:40的任务只能等待之前的任务执行完成才能够触发,所以要自己手动把定时任务设置成多线程的方式才行。

二. 场景复现
  项目描述:使用Springboot进行开发
  设置两个定时任务,每5s执行一次,并打印出其执行情况
  代码如下:

@Component
@Log4j2
public class ScheduledTask {
    @Scheduled(cron = "0/5 * * * * ?")
    public void task1() throws InterruptedException {
        log.info("I am task11111111, current thread: {}", Thread.currentThread());
        while (true) {
            //模拟耗时任务,阻塞10s
            Thread.sleep(10000);
            break;
        }
    }

    @Scheduled(cron = "0/5 * * * * ?")
    public void task2() {
        log.info("I am task22222222, current thread: {}", Thread.currentThread());
    }
}

  执行结果如下:

2019-04-24 17:11:15.008  INFO 16868 --- [   scheduling-1] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:15.009  INFO 16868 --- [   scheduling-1] com.example.demo.task.ScheduledTask      : I am task11111111, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:25.009  INFO 16868 --- [   scheduling-1] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:30.002  INFO 16868 --- [   scheduling-1] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:30.003  INFO 16868 --- [   scheduling-1] com.example.demo.task.ScheduledTask      : I am task11111111, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:40.004  INFO 16868 --- [   scheduling-1] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[scheduling-1,5,main]

  由结果可见,task1与task2由同一个线程Thread[scheduling-1,5,main]执行,也即该定时任务默认使用单线程,并且由于task1阻塞了10s,导致本应5s执行一次的定时任务10s才执行一次。

三. 解决方案
  网上有多种解决方案,以下列举两种
  方案一:使用@Async注解实现异步任务
    这种方式比较简单,在定时任务上加上@Async注解,注意:需启动类配合加上 @EnableAsync才会生效
  代码如下:

@Component
@Log4j2
public class ScheduledTask {
    @Async
    @Scheduled(cron = "0/5 * * * * ?")
    public void task1() throws InterruptedException {
        log.info("I am task11111111, current thread: {}", Thread.currentThread());
        while (true) {
            //模拟耗时任务,阻塞10s
            Thread.sleep(10000);
            break;
        }
    }

    @Async
    @Scheduled(cron = "0/5 * * * * ?")
    public void task2() {
        log.info("I am task22222222, current thread: {}", Thread.currentThread());
    }
}

  运行结果:

2019-04-24 17:03:00.024  INFO 2152 --- [         task-1] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[task-1,5,main]
2019-04-24 17:03:00.024  INFO 2152 --- [         task-2] com.example.demo.task.ScheduledTask      : I am task11111111, current thread: Thread[task-2,5,main]
2019-04-24 17:03:05.001  INFO 2152 --- [         task-3] com.example.demo.task.ScheduledTask      : I am task11111111, current thread: Thread[task-3,5,main]
2019-04-24 17:03:05.001  INFO 2152 --- [         task-4] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[task-4,5,main]
2019-04-24 17:03:10.002  INFO 2152 --- [         task-5] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[task-5,5,main]
2019-04-24 17:03:10.003  INFO 2152 --- [         task-6] com.example.demo.task.ScheduledTask      : I am task11111111, current thread: Thread[task-6,5,main]

  由运行日志可见,定时每5s执行一次已生效,且每次任务使用的线程不一样,也即实现了多线程执行定时任务,不会出现任务等待现象。此方式据说默认线程池大小为100,要是任务不多的话有点大材小用了,所以我觉得第二种方式比较好。
  方案二:手动设置定时任务的线程池大小
  定时任务代码部分还原,不使用@Async注解,新增启动代码配置:

@Configuration
public class AppConfig implements SchedulingConfigurer {
    @Bean
    public Executor taskExecutor() {
    	//指定定时任务线程数量,可根据需求自行调节
        return Executors.newScheduledThreadPool(3);
    }

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

  运行结果如下:

2019-04-24 17:26:15.008  INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]
2019-04-24 17:26:15.008  INFO 2164 --- [pool-1-thread-1] com.example.demo.task.ScheduledTask      : I am task11111111, current thread: Thread[pool-1-thread-1,5,main]
2019-04-24 17:26:20.002  INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]
2019-04-24 17:26:25.001  INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]
2019-04-24 17:26:30.001  INFO 2164 --- [pool-1-thread-1] com.example.demo.task.ScheduledTask      : I am task11111111, current thread: Thread[pool-1-thread-1,5,main]
2019-04-24 17:26:30.001  INFO 2164 --- [pool-1-thread-3] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[pool-1-thread-3,5,main]
2019-04-24 17:26:35.001  INFO 2164 --- [pool-1-thread-3] com.example.demo.task.ScheduledTask      : I am task22222222, current thread: Thread[pool-1-thread-3,5,main]

  由结果可见,第二种方式也实现了多线程任务调度。
四. 总结
  两种方式各有优缺点:

比较 方案一 方案二
优点 注解方式使用简单,代码量少 配置灵活,线程数可控
缺点 线程数不可控,可能存在资源浪费 需要增加编码

  留个坑,从日志上看@Async方式针对同一任务也是异步的,也即task1每5s会执行一次,但是方式二貌似对同一个任务不会生效,task1执行的时候需等待上一次执行结束才会触发,并没有每5s执行一次。关于这个现象,下次再琢磨…

参考链接:https://segmentfault.com/a/1190000015267976

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring多定时任务@Scheduled执行阻塞问题 的相关文章

  • WordPress出现Briefly unavailable for scheduled maintenance. Check back in a minute. 的解决方法

    WordPress出现 Briefly unavailable for scheduled maintenance Check back in a minute 解决方法 xff1a 登入FTP xff0c 然后把WordPress根目录的
  • SpringBoot通过HttpClient方式调用Restful接口

    前言 HttpClient相比于传统jdk自带的URLConnection 增加了易用性和灵活性 它不仅是客户端发送http请求变得容易 而且也方便了开发人员测试接口 提高了开发的效率 HttpClient是Apache Jakarta C
  • bom 与 dom

    1 什么是bom bom 是 Borwer Object Model 的缩写 中文是浏览器对象模型 作用 用来包含所有的浏览器信息 它有7个对象 window 当新打开一个新的窗口就会产生一个window对象 alert 警告框 var b
  • 三元运算符判断字符串是否为空

    有一个变量String userId 判断是否为null 如果为null 就赋值为空串 否则就不变 用if条件写是 if null userId userId 想用三元运算符写 常见错误写法 userId null userId 这样是错误
  • 熬夜总结的2022java面试题

    java面试宝典 前言 java基础 什么是面向对象 值传递和引用传递 和equals的区别是什么 重载和重写的区别 抽象类和接口的区别 构造器 Constructor 是否可被 override java静态变量 代码块 和静态方法的执行
  • Spring boot定时任务@Scheduled

    文章目录 1 前言 2 pom包配置 3 启动类启用定时 4 创建定时任务实现类 5 补充 cron表达式 6 遇到的坑 1 前言 Scheduled 参数可以接受两种定时的设置 一种是我们常用的cron 6 一种是 fixedRate 6
  • Spring 定时任务之 @Scheduled cron表达式

    一个cron表达式有至少6个 也可能7个 有空格分隔的时间元素 按顺序依次为 秒 0 59 分钟 0 59 小时 0 23 天 月 0 31 但是你需要考虑你月的天数 月 0 11 天 星期 1 7 1 SUN 或 SUN MON TUE
  • Spring多定时任务@Scheduled执行阻塞问题

    一 问题描述 最近项目中发现一个问题 计划每日凌晨4 40执行一个定时任务 使用注解方式 Scheduled cron 0 40 4 cron表达式明显没有问题 但是这个定时任务总是不按时执行 有时候得等到8点多 有时候9点多才执行 后来查
  • JAVA学习路线,面试复习方向指引

    前言 好久没有沉下心学习一波了 总结了一份简单的java学习内容 包含java开发大概的技术栈 后续每个部分寻找一些面试题专项学习 本篇先写一个大概的知识概括 后面逐渐加内容 慢慢丰满 有一起学习的朋友欢迎交流 共同进步 学问须学 不学则殆
  • Vue+SpringMVC---前后端分离极简尝试

    前后端分离 的开发方式是目前WEB开发中的一个大的趋势 随着各种前后端框架的出现 加上REST编程规范慢慢深入人心 前端后端之间通过更加轻量级 简洁高效的JSON作为数据传输格式 使得一切变得开朗起来 前后端分工更加明晰 前端被赋予了更多的
  • Java Optional类说明及使用(JDK8)

    Optional类是JDK8提供的类 用于防止出现空指针异常 本篇旨在对该类进行说明及具体使用方式列举 一 序言 Option在使用中主要是为了简化传统Java的if else形式对null情况进行判断 既然为了简化代码编写 就必须要提到J
  • Spring @Scheduled @Async联合实现调度任务

    定时任务之前一直用的是quartz之类 但是注意到Spring中其实也提供了一种简单的调度注释 Scheduled 也就想尝一下鲜 代码示意如下 Component EnableScheduling public class AsyncTa
  • mac os 安装 redis

    mac os 安装 redis 在redis官网下载 https redis io download 1 下载 在mac os系统 双指点击 finder 图标 选 Go to Folder 输入 usr local 另外开一个finder
  • springboot 整合 mybatis 报错: Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException

    Caused by org springframework beans factory NoSuchBeanDefinitionException No qualifying bean of type com mybatis springb
  • spring系列文章(一) 关于IDEA中 add framework support没有web application选项的问题

    今天在回顾smm框架时发现一个问题 也就是在add framework support没有web application选项的问题 问题原因 说明你未完全添加web支持 但是系统认定你有web支持 为什么你没有web application
  • macOS安装Homebrew

    Homebrew官网 http brew sh index zh cn html 方式一 官网安装 Homebrew的安装很简单 mac自带ruby环境 只需在终端下输入如下指令即可完成Homebrew的安装 如果以下链接失效可以去官网看看
  • Java POI 百万规模数据的导入和导出

    目录 1 百万数据导入 1 1 需求分析 1 2 思路分析 1 3 代码实现 1 3 1 步骤分析 1 3 2 自定义处理器 1 3 3 自定义解析 1 3 4 测试 2 百万数据导出 2 1 概述 2 2 解决方案分析 2 3 原理分析
  • maven集成cucumber,mvn test单元测试不运行

    maven集成cucumber mvn test单元测试不运行 项目已集成cucumber jacoco测试覆盖率100 在application项目添加单元测试 覆盖率下降 发现单元测试覆盖的语句覆盖率没有统计到 经试验 发现是appli
  • idea+springboot启动报错 ERROR org.apache.catalina.core.ContainerBase

    用idea导入了一个spring boot的项目 结果启动报错 ERROR org apache catalina core ContainerBase A child container failed during start tomca
  • @Scheduled参数及cron表达式解释

    Scheduled支持以下8个参数 1 cron 表达式 指定任务在特定时间执行 2 fixedDelay 表示上一次任务执行完成后多久再次执行 参数类型为long 单位ms 3 fixedDelayString 与fixedDelay含义

随机推荐

  • 《电子相框》--2.fb设备与图片显示

    接着上一篇博客的总结 继续项目的技术点展示 一 fb设备显示图片基础的步骤 1 确定打开的设备 一般设备在 dev fbxx 2 两个与显示有关的结构体变量 struct fb fix screeninfo finfo struct fb
  • ajax加密url参数,JS加解密URL参数encodeURIComponent() decodeURIComponent()

    参考1 http www w3school com cn js jsref encodeURIComponent asp 参考2 http www w3school com cn js jsref decodeURIComponent as
  • JS原型详解

    原型 原型是 JavaScript 面向对象特性中重要的概念 也是大家太熟悉的概念 因为在绝大多 数的面向对象语言中 对象是基于类的 例如 Java 和 C 对象是类实例化的结果 而在 JavaScript 语言中 没有类的概念 对象由对象
  • 用NCL将GRIB/GRIB2文件转成nc文件(批量转),JRA-55再分析为例

    背景 答主最近需要用到JRA 55再分析数据 但在面对GRIB数据格式时犯难了 便想把GRIB格式转成nc文件再做分析 因为nc文件很容易用python或Matlab处理 尝试了好些方法 发现先安装NCL再用ncl来批量转换 是一种比较便捷
  • windows下安装RabbitMQ

    目录 windows下载与安装 启动RabbitMQ 本篇博客下安装的均是目前最新版本 windows下载与安装 RabbitMQ官网 https www rabbitmq com 截止到现在RabbitMQ最新版本是3 10 7 Rabb
  • 【UE4】TSubclassOf模板类

    TSubclassOf是提供UClass类型安全性的模板类 模板类告知编辑器的属性窗口 只显示派生自AFPSProjectileActor的类 同时 这个参数在代码中也只接受派生自AFPSProjectileActor的类 当不加TSubc
  • docker标准输出日志存储位置,设置docker日志文件大小

    目录标题 docker日志存储位置 docker容器日志导致磁盘空间爆满 设置docker容器日志大小 全局设置 k8s中的容器日志 docker日志存储位置 在Linux系统中docker启动后日志存储在 var lib docker c
  • JSON parse error: Cannot deserialize value of type `java.util.Date` from String 2023-02-19 00:00:00

    问题描述 正常post请求然后接日期参数的时候报的异常 解决方案 添加 JsonFormat pattern yyyy MM dd HH mm ss timezone GMT 8 DateTimeFormat是用来格式化parm传参的 而接
  • 走进 San CLI(上):使用介绍

    本文是 San CLI 的使用和原理的第一篇 主要介绍 San CLI 的初衷和使用 下一篇介绍具体的实现原理 什么是 CLI CLI 是命令行界面 command line interface 的英文缩写 命令行界面是在图形用户界面得到普
  • Qt 实现按分钟更新显示当前时间

    以下方法分享按分钟更新时间 希望对大家有帮助 QTimer timer new QTimer this timer gt setSingleShot true connect timer SIGNAL timeout this SLOT u
  • npm未能加载Visual C++组件,解决办法win10

    错误提示如下 以管理员身份运行 Windows PowerShell npm install global production windows build tools npm install g node gyp
  • i2c-tools-v3.1.2移植

    1 工具 2 放到linux中解压 3 配置Makefile 4 make 成功后会在tools目录下生成 i2cdetect i2cdump i2cget i2cset等工具 5 将i2cdetect放到终端
  • postgresql 操作查询jsonb数据

    1 操作键值对 PostgreSQL 对 jsonb 类型的筛选查询可以使用 gt 或者 gt gt 操作符 gt 操作符用于通过 JSON 对象中的键来获取对应的值 gt gt 操作符可以将获取到的值转化为字符串类型 例如 下面是一个包含
  • UI自动化测试定位元素工具--Weditor

    Weditor 前置条件 1 安装Pycharm 2 终端中输入 pip install weditor安装weditor 使用方法 weditor启动 python m weditor 连接设备成功后 可以看到入下图 主要有5个区域 红色
  • nth_element详解

    nth element 是c 的STL库中的函数 作用是将数组中第k小的整数放在区间第k个位置 比如a 6 2 5 6 4 7 8 使用nth element a a 3 a 6 后 区间中第四个数 也就是a 3 会被放入数组中第四小的数
  • 创建本地docker镜像仓库并push和pull

    解决如何在服务器上 或本地 创建docker镜像仓库并push镜像到本地仓库 然后从其他机器上pull本地仓库镜像 1 启动镜像registry 2 docker run d p 5000 5000 restart always name
  • 基于Dockerfile构建LNMP环境(php7+mysql+nginx) --原创

    构建LNMP环境 php7 mysql nginx 原创 经几个星期反复测试总结出了整个lnmp环境的Dockerfile文件 并已经适用于公司开发环境中 centOS7 4 1708 tengine 2 1 2 php 7 0 17 PH
  • 对华为招聘人才的一点看法

    导读 首先 华为招聘搞的是海笔和海面 所以场面很混乱 华为不刷简历 不刷笔试 我真不明白 对于这个 我们可以给两个理由去解释 第一 就是华为仅仅是通过自己的校园招聘去宣传华为 我知道去年华为来天津的学校招聘 第一次来时 我们学校的人一个都没
  • 与甲方的项目软件服务合同参考模板--PM所需

    编号 此处换XX公司LOGO 国内领先APP开发服务商 技 术 开 发 购 销 合 同 甲 方 地 址 电话 传真 邮 箱 项目联系人1 电话 微信 项目联系人2 电话 微信 乙 方 XX科技有限公司 地 址 电话 传真
  • Spring多定时任务@Scheduled执行阻塞问题

    一 问题描述 最近项目中发现一个问题 计划每日凌晨4 40执行一个定时任务 使用注解方式 Scheduled cron 0 40 4 cron表达式明显没有问题 但是这个定时任务总是不按时执行 有时候得等到8点多 有时候9点多才执行 后来查