Spring Task 定时任务没有定时执行是为什么?

目录

      • SpringBoot 定时任务的原理
      • 任务一直阻塞会怎么样?
      • 多个定时任务的执行
      • 具有相同表达式的定时任务,它们的执行顺序如何?
      • Spring Task 和 Linux crontab 的 cron 语法区别?
      • 在 cron 语法中容易犯的错误
      • @Async 异步注解原理及作用
      • 并发执行任务如何配置?
      • 其他问题
      • 总结

在日常开发中,定时任务的应用已经变得十分常见,例如定时发送邮件、短信,数据定时转储等。然而,有时候我们会遇到定时任务没有按照预期执行的情况。本文将讨论 Spring Task 中定时任务执行的原理以及可能遇到的相关问题。

SpringBoot 定时任务的原理

绝大部分开发者在使用 Spring Boot 时都会使用它提供的定时任务 Starter 和定时任务的注解。因此,让我们首先了解一下 Spring Boot 实现定时任务的原理以及相关注解的作用。

自 Spring 3.0 版本以后,Spring 使用 @Scheduled 注解来支持定时任务。

在使用时,我们需要在应用的启动类上加上 @EnableScheduling 注解,该注解从 Spring 3.1 开始提供。

然而,在 Spring 3.0 版本之前,我们通常会通过 XML 配置和 @Scheduled 注解配合使用来实现定时任务。而 @EnableScheduling 注解实际上相当于该 XML 配置的简化版。它的作用是发现标记了 @Scheduled 注解的方法,没有该注解的方法将不会被执行。但是在大多数情况下,我们只需要关注目标实现,而不必深究其背后的细节。

任务一直阻塞会怎么样?

为了更好地理解定时任务的执行过程,我们进行了一个简单的实验:编写一个每隔 20 秒执行一次的定时任务,并在其中加入一个断点。

实验结果显示,当遇到断点时,后续的任务会被阻塞。这是因为线程池中只有一个线程用于执行任务,而该线程被阻塞后,后续任务将无法执行。线程池内部采用 DelayQueue 延迟队列实现,其特点是无界、延迟、阻塞,能够按照一定的顺序执行工作队列中的元素。

多个定时任务的执行

根据前面的实验结果,我们知道默认情况下,任务的线程池只有一个线程,因此多个定时任务应该是串行执行的。如果一个任务被阻塞,其他任务也会受到影响。

那么,如果我们将线程池的线程数设置为多个,会发生什么呢?实验结果显示,即使线程池中包含多个线程,多个定时任务仍然是串行执行的。只有在使用自定义的线程池,并且在任务上加上 @Async 注解时,才能实现并发执行。

具有相同表达式的定时任务,它们的执行顺序如何?

具有相同表达式的定时任务的执行顺序与调度有关。默认情况下,它们是串行执行的,首先获取到 CPU 时间片的任务会先执行。在多线程的情况下,具体的执行顺序取决于线程池的线程数、所用队列等因素。

Spring Task 和 Linux crontab 的 cron 语法区别?

两者的 cron 表达式非常相似,但需要注意的是,Linux 的 crontab 只提供了分钟级别的最小粒度,而 Spring Task 的最小粒度从秒开始。

在 cron 语法中容易犯的错误

在编写 cron 表达式时,很容易犯一些错误。例如,要求编写每十分钟执行一次的 cron 语句时,可能会写成类似以下的版本:

0 0/10 * * * ?

因此,在编写 cron 表达式后,建议适当降低执行间隔时间进行测试,或者使用在线工具检测 cron 脚本是否正确。

@Async 异步注解原理及作用

Spring Task 中与异步相关的注解有两个,一个是 @EnableAsync,另一个是 @Async

默认情况下,@Async 注解会使方法仍然由一个线程同步执行。要想实现异步执行,需要在启动类上加上 @EnableAsync 注解,并定义一个线程池。

并发执行任务如何配置?

我们可以通过两种方式来配置并发执行任务:

  1. 将默认的线程池替换为自定义的线程池。
  2. 不改变任务调度器默认使用的线程池,而是将任务交给一个异步线程池去执行。

通过这些方式,我们可以让任务高效地并发执行,提高系统的性能。

方式一,我们可以将默认的线程池替换为我们自定义的线程池。通过ScheduleConfig配置文件实现SchedulingConfigurer接口,并重写setSchedulerfang方法。可实现AsyncConfigurer接口复写getAsyncExecutor获取异步执行器,getAsyncUncaughtExceptionHandler获取异步未捕获异常处理器@Configurationpublic
class ScheduleConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));}
}
方式二:不改变任务调度器默认使用的线程池,而是把当前任务交给一个异步线程池去执行。@Scheduled(fixedRate = 1000*10,initialDelay = 1000*20)@Async("hyqThreadPoolTaskExecutor")public void test(){System.out.println(Thread.currentThread().getName()+"--->xxxxx--->"+Thread.currentThread().getId());}//自定义线程池@Bean(name = "hyqThreadPoolTaskExecutor")public TaskExecutor  getMyThreadPoolTaskExecutor() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();taskExecutor.setCorePoolSize(20);taskExecutor.setMaxPoolSize(200);taskExecutor.setQueueCapacity(25);taskExecutor.setKeepAliveSeconds(200);taskExecutor.setThreadNamePrefix("hyq-threadPool-");taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());taskExecutor.setWaitForTasksToCompleteOnShutdown(true);taskExecutor.setAwaitTerminationSeconds(60);taskExecutor.initialize();return taskExecutor;

其他问题

  • 如果定时任务没有生效,需要检查是否加上了 @EnableScheduling 注解。
  • 如果异步任务没有生效,需要检查是否加上了 @EnableAsync 注解,并且定义了线程池,否则仍然是串行执行的。

总结

本文介绍了 Spring Boot 定时任务的原理,通过实验探究了延迟队列及串行、并行、并发的概念。对比了 Linux 下的 crontab 和 Spring 的 cron 表达式区别以及常见的错误。最后通过实验异步注解,两种方式配置线程池,使任务能够高效运行。希望本文能够对你有所帮助。

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

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

相关文章

优化sqlserver中的 not like

如果你想要优化一个查询,特别是当使用 NOT LIKE 来排除包含某个字符(如 ;)的记录时,确保查询能够高效执行的关键是索引和查询结构。但是,对于 NOT LIKE 操作符来说,特别是当模式以通配符 % 开头时&#xff…

【ROMA核心特性数据、服务、消息、设备集成及统一运维】

1、数据集成 FDI旨在解决多种数据源的快速灵活集成能力,您可以在任意时间、任意地点、任意系统之间实现实时数据订阅和定时增量数据迁移。 (1)数据集成任务的生命周期管理 (2)FDI支持修改数据集成任务的信息、查看数…

初识Node.js-认识node(安装Node.js环境配置)

目录 一、node介绍 1.概念和特点 2.核心功能 3.应用场景 二、Node初使用 1.安装node配置 windows上安Node.js 1.windows安装包(.msi) 2、Windows 二进制文件 (.exe)安装 Linux 上安装 Node.js 直接使用已编译好的包 Ubuntu 源码安装 Node.js …

【JVM】垃圾回收机制(Garbage Collection)

目录 一、什么是垃圾回收? 二、为什么要有垃圾回收机制(GC)? 三、垃圾回收主要回收的内存区域 四、死亡对象的判断算法 a)引用计数算法 b)可达性分析算法 五、垃圾回收算法 a)标记-清除…

GDPU 天码行空11

(一)实验目的 1、掌握JAVA中IO中各种类及其构造方法; 2、重点掌握IO中类所具有的IO操作方法; 3、熟悉软件中登录模块的开发方法; 4、掌握IO中读写常用方法。 5、进一步熟悉正则规则的使用方法。 (二&…

上岸武汉顶级985!苦尽甘来的那一天,山河星月都作贺礼。

今天分享经验的同学是小马哥梦马强化班的学员,一战高分上岸武汉大学! 经验分享 很高兴有机会在这里给大家分享我的考研历程。 首先介绍一下我自己,我本科就读于吉林大学空间信息与数字技术,成绩不是很好。六级是在考研期间12月…

C语言逻辑语句

叠甲:以下文章主要是依靠我的实际编码学习中总结出来的经验之谈,求逻辑自洽,不能百分百保证正确,有错误、未定义、不合适的内容请尽情指出! 文章目录 1.何为控制语句2.控制语句-分支语句2.1.if2.2.switch3.控制语句-循环语句3.1.while3.2.do...while3.3.for4.控制语句-转向…

ue引擎游戏开发笔记(32)——为游戏添加新武器装备

1.需求分析: 游戏中角色不会只有一种武器,不同武器需要不同模型,甚至可能需要角色持握武器的不同位置,因此需要添加专门的武器类,方便武器后续更新,建立一个武器类。 2.操作实现: 1.在ue5中新建…

如何用DeepDiff测接口数据源变更?

开发同学最近变更了部分业务查询接口底层的数据源,希望测试同学能够针对这些接口进行一些回归验证,校验底层数据源更新前后业务查询接口返回的一致性,保证更新后对正常业务没有影响。 这个回归测试和一般接口测试有所区别,不仅仅…

C++基础-编程练习题2

文章目录 前言一、查找“支撑数”二、数组元素的查找三、爬楼梯四、数字交换五、找高于平均分的人 前言 C基础-编程练习题和答案 一、查找“支撑数” 【试题描述】 在已知一组整数中, 有这样一种数非常怪, 它们不在第一个, 也不在最后一个&…

使用Simulink Test进行单元测试

本文摘要:主要介绍如何利用Simulink Test工具箱,对模型进行单元测试。内容包括,如何创建Test Harness模型,如何自动生成excel格式的测试用例模板来创建测试用例,如何手动填写excel格式的测试用例模板来手动创建测试用例…

精通 Docker:简化开发、部署与安全保障

踏上 Docker 之旅,每一条命令都是高效与可靠的新境界。Docker 彻底改变了软件开发,为构建、部署和保障应用程序提供了前所未有的便利。从打造精益敏捷的镜像到编排复杂的微服务架构,Docker 让开发人员和运维人员都倍感轻松。让我们深入探索 D…

Redis---------实现查询缓存业务

目录 数据库与缓存之间的工作业务逻辑: 接下来看查询缓存代码实现,主要是捋清楚业务逻辑,代码实现是死的: Controller: Service: P37作业实现:总体逻辑跟上面的业务逻辑差不多 Controller: Service&#…

头歌-Java编程基础进阶

第1关 两整数的四则运算 package step1;import java.util.Scanner;public class Arithmetic2Num {public static void main(String[] args) { // ---------------------Begin------------------------Scanner scnew Scanner(System.in);int asc.nextInt();int bsc.nextInt();…

对象存储的几个概念

媒体存储-帮助中心 - 天翼云 媒体存储 对象存储(经典版)I型 -帮助中心- 天翼云 OOS https://www.ctyun.cn/document/10026735/10028989 ZOS 成长地图_对象存储服务 OBS OBS 以上是对象存储 的几个概念,可以反复的理解下。

Azure AKS日志查询KQL表达式

背景需求 Azure(Global) AKS集群中,需要查询部署服务的历史日志,例如:我部署了服务A,但服务A的上一个版本Pod已经被杀掉由于版本的更新迭代,而我在命令行中只能看到当前版本的pod日志&#xff…

SparkSql介绍

概述 SparkSQL,顾名思义,就是Spark生态体系中的构建在SparkCore基础之上的一个基于SQL的计算模块。SparkSQL的前身不叫SparkSQL,而叫Shark,最开始的时候底层代码优化,sql的解析、执行引擎等等完全基于Hive&#xff0c…

使用 Lambda 匿名函数在 Python 中轻松地进行排序

排序是 Python 编程中的常见操作,Python 提供了许多强大的函数方法方便的完成排序功能,比如 sorted() 和 sort()。在本文中,我们将结合 lambda 函数进行排序。它被称为匿名函数,可以灵活轻松地完成各种形式的排序。 字符串列表排…

前端安全防护实战:XSS、CSRF防御与同源策略详解(react 案例)

前端安全防护实战中,主要涉及三个方面:XSS (Cross-Site Scripting) 攻击的防御、CSRF (Cross-Site Request Forgery) 攻击的防御,以及浏览器的同源策略。以下是这三个方面的详细说明: XSS 防御详解 XSS 概述 XSS攻击是一种让攻…

科创板门槛升级!解析中国量子企业的上市之路与国际比拼

4月30日晚,中国证监会于发布了修订后的《科创属性评价指引(试行)》(以下简称“新指引”),该指引自发布日起正式生效。本次修订对原有指引中的部分标准进行了调整,具体如下: 1&#x…