Spring中的任务调度:探索@Scheduled和@Schedules注解的威力

Spring中的任务调度:探索@Scheduled和@Schedules注解的威力

  • 前言
  • 第一部分:什么是定时任务
  • 第二部分:@Scheduled和@Schedules注解详解
    • @Scheduled注解
      • 常用的`@Scheduled`注解属性:
    • @Schedules注解
    • cron表达式详解
  • 第三部分:高级用法
    • 1. 传递参数给定时任务方法:
    • 2. 异常处理和错误处理策略:
    • 3. 启用异步定时任务:
  • 第四部分:最佳实践

前言

在现代应用程序开发中,执行定时任务是一个常见的需求。无论是定期执行批处理作业、发送电子邮件通知,还是清理无用数据,定时任务在许多应用中都扮演着重要角色。Spring框架为处理这一需求提供了强大的工具,其中@Scheduled@Schedules注解就像是这个领域的秘密武器。这篇博客将带你深入探讨这两个注解,解释它们的工作原理,以及如何在Spring应用程序中使用它们来管理各种定时任务。

第一部分:什么是定时任务

定时任务是一种在应用程序中执行预定任务或操作的机制。这些任务可以按照预定的时间、日期或周期性地执行,通常用于执行一些自动化的操作,如数据备份、报告生成、系统维护等。定时任务在应用程序开发中非常重要,原因如下:

  1. 自动化处理: 定时任务允许开发人员自动执行重复性或计划性的任务,而无需手动干预。这可以提高工作效率,减少人为错误的风险,并节省时间和资源。

  2. 数据处理: 定时任务经常用于数据处理,例如定期从外部数据源获取数据、清洗数据、将数据导入数据库等。这确保了数据一致性和及时性。

  3. 系统维护: 定时任务可以用于执行系统维护任务,如日志文件的清理、数据库索引的重建、服务器性能监控等。这有助于确保应用程序的稳定性和性能。

  4. 计划任务: 对于需要按计划执行的任务,例如发送定期报告或通知,定时任务是理想的解决方案。这有助于确保任务按时执行,不会被遗漏。

  5. 资源管理: 定时任务可以帮助有效管理系统资源。例如,可以按需启动和停止资源密集型任务,以充分利用服务器资源,而不会导致资源浪费。

在软件开发中,通常使用编程语言或框架提供的定时任务调度器或库来创建和管理定时任务。这些定时任务通常会伴随着代码实现,以确保任务的正确执行,并且可以在需要时进行监控和日志记录。通过良好的注释,可以使代码更易于维护和扩展,同时有助于其他开发人员了解任务的目的和功能。

第二部分:@Scheduled和@Schedules注解详解

当涉及到Spring框架中的定时任务支持,有两种主要的注解,即@Scheduled@Schedules,它们允许您在应用程序中执行周期性任务。以下是更详细的解释:

@Scheduled注解

@Scheduled注解用于将一个方法标记为定时任务,该方法将根据指定的时间表执行。您可以将@Scheduled注解应用于Spring管理的Bean的方法。

常用的@Scheduled注解属性:

  1. fixedRate属性:根据固定的频率执行任务。

    @Scheduled(fixedRate = 5000) // 每隔5秒执行一次
    
  2. fixedDelay属性:任务完成后,等待一段固定的时间再执行下一次。

    @Scheduled(fixedDelay = 5000) // 任务执行完后,等待5秒再执行下一次
    
  3. initialDelay属性:在应用启动后,首次执行任务前的延迟时间。

    @Scheduled(initialDelay = 3000, fixedRate = 5000) // 启动后等待3秒,然后每隔5秒执行一次
    
  4. cron属性:使用Cron表达式定义任务的执行时间,可以实现高度灵活的调度。

    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    

@Schedules注解

@Schedules注解是一个容器注解,允许同时指定多个@Scheduled注解的配置。这对于定义多个不同时间表的定时任务非常有用。您可以在同一个方法上应用多个@Scheduled注解,或者使用@Schedules将它们封装在一个容器内。

@Schedules({@Scheduled(fixedRate = 5000), // 每隔5秒执行一次@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
})
public void myScheduledMethods() {// 定时任务执行的代码
}

这些注解允许您在Spring应用程序中轻松地创建和管理定时任务。您可以根据您的需求选择合适的时间表和任务调度策略。通过这种方式,您可以自动执行各种任务,例如数据清理、通知生成、定期报告等。同时,使用适当的注释和文档,可以使代码更具可读性和可维护性。

cron表达式详解

Cron表达式是一种灵活而强大的方式,用于定义定时任务的执行时间。它通常由6或7个字段组成,分别表示秒、分钟、小时、一个月中的哪一天、月份、一个星期中的哪一天,以及可选的年份字段。Cron表达式的语法如下:

┌───────────── 秒 (0 - 59)
│ ┌───────────── 分钟 (0 - 59)
│ │ ┌───────────── 小时 (0 - 23)
│ │ │ ┌───────────── 一个月中的哪一天 (1 - 31)
│ │ │ │ ┌───────────── 月份 (1 - 12 或 JAN-DEC)
│ │ │ │ │ ┌───────────── 一个星期中的哪一天 (0 - 6 或 SUN-SAT, 7表示SUN)
│ │ │ │ │ │ ┌───────────── 年份 (可选)
│ │ │ │ │ │ │
│ │ │ │ │ │ │
* * * * * * *

以下是对每个字段的详细说明:

  1. 秒 (0 - 59): 表示一分钟内的秒数。例如,0表示每分钟的开始时执行任务,30表示每分钟的30秒时执行任务。

  2. 分钟 (0 - 59): 表示一小时内的分钟数。例如,0表示每小时的开始时执行任务,30表示每小时的30分钟时执行任务。

  3. 小时 (0 - 23): 表示一天内的小时数。例如,0表示每天的午夜执行任务,12表示每天中午执行任务。

  4. 一个月中的哪一天 (1 - 31): 表示一个月内的具体日期。例如,1表示每月的第一天执行任务,15表示每月的15号执行任务。

  5. 月份 (1 - 12 或 JAN-DEC): 表示一年内的月份。您可以使用数字(1 - 12)或缩写的月份名称(JAN-DEC)。例如,1或JAN表示一月,12或DEC表示十二月。

  6. 一个星期中的哪一天 (0 - 6 或 SUN-SAT, 7表示SUN): 表示一周内的具体日期。您可以使用数字(0 - 6,其中0表示星期日)或缩写的星期名称(SUN-SAT)。例如,1或MON表示星期一,7或SUN表示星期日。

  7. 年份 (可选): 此字段是可选的,用于指定任务执行的年份。通常情况下,您不需要指定年份。

下面是一些示例Cron表达式:

*/5 * * * * ? 每隔5秒执行一次
0 */1 * * * ? 每隔1分钟执行一次
0 0 5-15 * * ? 每天5-15点整点触发
0 0/3 * * * ? 每三分钟触发一次
0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点0 0 12 ? * WED 表示每个星期三中午12点
0 0 17 ? * TUES,THUR,SAT 每周二、四、六下午五点
0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
0 0 23 L * ? 每月最后一天23点执行一次
0 15 10 L * ? 每月最后一日的上午10:15触发
0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
0 15 10 * * ? 2005 2005年的每天上午10:15触发
0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发30 * * * * ? 每半分钟触发任务
30 10 * * * ? 每小时的10分30秒触发任务
30 10 1 * * ? 每天1点10分30秒触发任务
30 10 1 20 * ? 每月20号1点10分30秒触发任务
30 10 1 20 10 ? * 每年10月20号1点10分30秒触发任务
30 10 1 20 10 ? 2011 2011年10月20号1点10分30秒触发任务
30 10 1 ? 10 * 2011 2011年10月每天1点10分30秒触发任务
30 10 1 ? 10 SUN 2011 2011年10月每周日1点10分30秒触发任务
15,30,45 * * * * ? 每15秒,30秒,45秒时触发任务
15-45 * * * * ? 15到45秒内,每秒都触发任务
15/5 * * * * ? 每分钟的每15秒开始触发,每隔5秒触发一次
15-30/5 * * * * ? 每分钟的15秒到30秒之间开始触发,每隔5秒触发一次
0 0/3 * * * ? 每小时的第0分0秒开始,每三分钟触发一次
0 15 10 ? * MON-FRI 星期一到星期五的10点15分0秒触发任务
0 15 10 L * ? 每个月最后一天的10点15分0秒触发任务
0 15 10 LW * ? 每个月最后一个工作日的10点15分0秒触发任务
0 15 10 ? * 5L 每个月最后一个星期四的10点15分0秒触发任务
0 15 10 ? * 5#3 每个月第三周的星期四的10点15分0秒触发任务

Cron表达式非常灵活,可以满足各种复杂的调度需求。在Spring中,您可以使用@Scheduled注解中的cron属性来配置Cron表达式,以实现高度定制的定时任务。

第三部分:高级用法

在Spring框架中,您可以通过不同的方式传递参数给定时任务方法,并且可以实现异常处理和错误处理策略。此外,您还可以启用异步定时任务以提高性能。下面让我详细解释这些高级用法:

1. 传递参数给定时任务方法:

您可以通过@Scheduled注解传递参数给定时任务方法。以下是一个示例:

@Service
public class ScheduledTaskService {@Scheduled(fixedRate = 5000)public void taskWithParameters() {// 在定时任务方法中传递参数executeTask("Task with parameters", 42);}public void executeTask(String taskName, int value) {// 执行任务,并使用传递的参数System.out.println(taskName + " - Parameter value: " + value);}
}

在这个示例中,taskWithParameters方法是一个定时任务,它使用executeTask方法来执行任务,并传递了两个参数:任务名称和一个整数值。

2. 异常处理和错误处理策略:

在定时任务方法中,您可以使用标准的异常处理机制来处理异常。Spring提供了一种方式,可以将定时任务方法包装在一个try-catch块中,以处理可能抛出的异常。您也可以使用Spring的@Scheduled注解的@ExceptionHandler属性来指定异常处理方法。

以下是一个示例,演示如何处理定时任务方法中的异常:

@Service
public class ScheduledTaskService {@Scheduled(fixedRate = 5000)public void taskWithException() {try {// 可能会抛出异常的代码throw new RuntimeException("An error occurred");} catch (Exception e) {// 异常处理逻辑System.err.println("Exception caught: " + e.getMessage());}}
}

3. 启用异步定时任务:

要启用异步定时任务,您可以在定时任务方法上使用@Async注解,并在Spring配置中启用异步支持。以下是一个示例:

首先,确保您在Spring配置中启用了异步支持:

<task:annotation-driven executor="taskExecutor" />
<task:executor id="taskExecutor" pool-size="5" />

然后,在定时任务方法上使用@Async注解:

@Service
public class ScheduledTaskService {@Async@Scheduled(fixedRate = 5000)public void asyncTask() {// 异步执行的任务System.out.println("Async task is running...");}
}

这将使asyncTask方法在一个单独的线程中异步执行,而不会阻塞主线程。这对于执行耗时操作的定时任务非常有用,以提高应用程序的性能和响应速度。

请注意,启用异步定时任务需要适当的配置和线程池管理,以确保任务的正确执行和资源的合理利用。

第四部分:最佳实践

以下是编写可维护和高效的定时任务的最佳实践:

  1. 清晰的命名和注释

    • 为定时任务方法和类使用清晰、描述性的命名,以便其他开发人员可以轻松理解其用途。
    • 提供详细的注释,解释每个定时任务的目的、参数和特殊考虑事项。
  2. 分离业务逻辑

    • 将定时任务方法保持简洁,只包含与定时任务本身相关的逻辑。将任务的实际业务逻辑移到单独的服务或组件中,以提高代码的可测试性和可维护性。
  3. 错误处理

    • 实现适当的错误处理策略,以处理可能出现的异常情况。
    • 使用try-catch块来捕获异常,确保不会因异常而中断整个应用程序。
  4. 使用参数

    • 如果定时任务需要参数,请使用方法参数来传递它们,而不是硬编码在方法中。这使得定时任务更通用且易于维护。
  5. 定时任务的调度策略

    • 谨慎选择定时任务的调度策略(如fixedRatecron)以确保任务按照需求执行。
    • 考虑定时任务的并发性,以避免多个实例同时执行相同的任务。
  6. 异步任务

    • 使用@Async注解将耗时任务标记为异步,以提高应用程序的性能和响应速度。
  7. 监控和日志

    • 实现适当的日志记录,以允许在出现问题时进行故障排除。
    • 使用监控工具来跟踪定时任务的执行情况,以及任务是否按照计划执行。
  8. 测试

    • 编写单元测试来验证定时任务的逻辑和正确性。
    • 使用模拟或伪造对象来模拟定时任务的依赖项,以便更容易进行单元测试。
  9. 定时任务参数的外部配置

    • 避免硬编码定时任务的参数。使用外部配置文件或属性,以便在不重新编译代码的情况下修改定时任务的参数。
  10. 定时任务的可用性和稳定性

    • 考虑应对应用程序重启和故障恢复,以确保定时任务的可用性和稳定性。
    • 使用数据库或其他持久性存储来记录任务的执行状态,以便在应用程序崩溃后能够正确恢复。

通过遵循这些最佳实践,您可以编写可维护、高效且稳定的定时任务,确保它们在应用程序中按计划执行并符合业务需求。

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

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

相关文章

深入篇【C++】总结智能指针的使用与应用意义(auto_ptr/unique_ptr/shared_ptr/weak_ptr)底层原理剖析+模拟实现

深入篇【C】总结智能指针的使用与应用意义&&(auto_ptr/unique_ptr/shared_ptr/weak_ptr&#xff09;底层原理剖析模拟实现 智能指针的出现智能指针的使用应用意义/存在问题智能指针原理剖析模拟实现auto_ptrunique_ptrshared_ptrweak_ptr 智能指针的出现 首先我们要理…

【个人记录】Ceph添加OSD

目标 1.已存在Ceph集群2.添加node1盘 /dev/nvme1n1 /dev/nvme2n1进入ceph集群 步骤 1.格式化磁盘 ceph-deploy disk zap node1 /dev/nvme1n1 /dev/nvme2n12.添加磁盘到osd ceph-deploy osd create --data /dev/nvme1n1 node1 ceph-deploy osd create --data /dev/nvme2n1 …

vscode ssh linux C++ 程序调试

vscode调试c++程序相比vs2022要复杂很多,vs2022可以"一键运行调试",vscode则需要自己配置。 ​vscode调试程序时,会在当前工作目录产生.vscode 目录, 该目录有两个重要文件launch.json和tasks.json, 下面介绍两种调试方法: 手动调试和自动调试。 手动调试 不管…

VUE树结构实现

实现效果: 数据库表结构如下: 要求:需要有parentId,id。parentId就是父记录的id 表数据要求:一定不要让一条记录的parentid和id相同 前端代码: 注意:el-table标签里面需要加上属性,才可以有下拉箭头的样式 <el-table v-loading="listLoading" :data

MySQL中死锁

数据库的死锁是指不同的事务在获取资源时相互等待&#xff0c;导致无法继续执行的一种情况。当发生死锁时&#xff0c;数据库会自动中断其中一个事务&#xff0c;以解除死锁。在数据库中&#xff0c;事务可以分为读事务和写事务。读事务只需要获取读锁&#xff0c;而写事务需要…

Spring Boot中的异步编程:解决的问题与应用场景

Spring Boot中的异步编程&#xff1a;解决的问题与应用场景 在现代Web应用程序中&#xff0c;高并发和性能是至关重要的。为了处理大量的请求和任务&#xff0c;异步编程成为了不可或缺的一部分。Spring Boot提供了强大的异步编程支持&#xff0c;可以显著提高应用程序的吞吐量…

java集合常用方法汇总

集合排序链接 集合排序链接 1.新建集合 List<String> result Lists.newArrayList();2.集合赋值 List<String> orderStatusList Lists.newArrayList("60", "70", "90");3.遍历集合 list.stream().map(CspTransferOrderInfo::ge…

【Java 进阶篇】JavaScript Math对象详解

在JavaScript编程中&#xff0c;Math对象是一个非常有用的工具&#xff0c;用于执行各种数学运算。它提供了许多数学函数和常数&#xff0c;可以用于处理数字、执行几何运算、生成随机数等。在本篇博客中&#xff0c;我们将深入探讨JavaScript中Math对象的各种功能和用法。 什…

LiveMedia视频中间件视频隐私打码直播解决方案

一、方案背景 随着科技的发展&#xff0c;视频监控系统已经成为了我们生活中不可或缺的一部分。无论是在公共区域&#xff0c;还是在私人场所&#xff0c;我们都可以看到各种各样的监控设备。这些设备的出现&#xff0c;无疑提高了我们的生活安全&#xff0c;使得我们可以更好地…

Gin,Gorm实现Web计算器

目录 仓库链接0.PSP表格1. 成品展示1.基础运算2. 清零回退3.错误提示4.历史记录拓展功能1.前端可修改的利率计算器2.科学计算器3. 按钮切换不同计算器模式4.用户在一次运算后不清零继续输入操作符&#xff0c;替换表达式为上次答案 2.设计实现过程3.代码说明4.心路历程和收获 仓…

【JavaSE API 】生成随机数的2种方法:Random类和Math类的Random方法

生成随机数的两种方法 Random类和Math类的random方法都可以用来生成随机数 而Math类的random方法则是基于系统时间的伪随机数生成器&#xff0c;大于等于0.0小于1.0的随机double值范围[0,1)。例如&#xff1a; double num1 Math.random() * 5 4;//范围[4,9) Random类是基于种…

企业级CI/CD 持续集成/交付/发布

jenkins 安装与使用 nmcli g hostname jenkins 加载缓存 yum makecache fast 上传jdk11、jdk8 获取、上传war包 1、jenkins.io/download 2.4.27 2、老师发的 上传 maven 上传tomcat软件包 &#xff08;apache.org-tomcat8-下载&#xff09; 注意8009端口 /usr... vi /etc/pro…

react中ant.design框架配置动态路由

目录 什么是动态路由&#xff1f; 应用场景&#xff1a; ant.design动态路由如何配置&#xff1a; 首先&#xff1a;找到app.tsx文件 然后&#xff1a;找到menuHeaderRender 其次&#xff1a;修改menuHeaderRender为menuDataRender​编辑 最后&#xff1a;在箭头函数里re…

linux内存、cpu、进程、端口、硬盘管理

这里讲解一下linux内存、cpu、进程、端口、硬盘管理命令操作,更多linux常用命令见:一些经常使用的linux命令 一、内存、cup 管理 top 命令 1、top 命令的第一行 top - 10:11:23 up 12:10, 2 users, load average: 0.00, 0.02, 0.05 依次对应&#xff1a; 系统当前时间 10:11:…

Vite与Webpack谁更胜一筹,谁将引领下一代前端工具的发展

你知道Vite和Webpack吗&#xff1f;也许有不少“程序猿”对它们十分熟悉。 Webpack Webpack是一个JavaScript应用程序的静态模块打包工具&#xff0c;它会对整个应用程序进行依赖关系图构建。而这也会导致一个不可避免的情况&#xff0c;使用Webpack启动应用程序的服务器&…

C++指针解读(5)-- 指针和数组(多维数组)

相比一维数组&#xff0c;二维数组的概念和相关运算要复杂得多。 1、二维数组的存储及访问 假设有这么一个二维数组&#xff1a; int arr[3][4] {{ 10, 11, 12, 13 },{ 20, 21, 22, 23 },{ 30, 31, 32, 33 } }; 我们可以把二维数组看成数组的数组&#xff1a; &#xff…

136.只出现一次的数字

136. 只出现一次的数字 - 力扣&#xff08;LeetCode&#xff09; 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且…

Arduino驱动BNO055 10轴绝对定向传感器(惯性测量传感器篇)

目录 1、传感器特性 2、控制器和传感器连线图 3、驱动程序 BNO055是实现智能9轴绝对定向的新型传感器IC,它将整个传感器系统级封装在一起,集成了三轴14位加速度计,三轴16位陀螺仪,三轴地磁传感器和一个自带算法处理的32位微控制器。

在 Elasticsearch 中实现自动完成功能 3:completion suggester

在这篇博文中&#xff0c;我们将讨论 complete suggester - 一种针对自动完成功能进行优化的 suggester&#xff0c;并且被认为比我们迄今为止讨论的方法更快。 Completion suggester 使用称为有限状态转换器的数据结构&#xff0c;该结构类似于 Trie 数据结构&#xff0c;并且…

Net6 用imagesharp 实现跨平台图片处理并存入oss

项目要求&#xff1a;生成电子证书 一、模板文件在OSS中&#xff0c;直接加载 二、向模板文件添加二维码 三、向模板文件添加多行文字 四、生成二维码&#xff0c;存入本地&#xff0c; 五、向模板文件添加二维码 代码实现步骤 一、建立.net 6 API项目&#xff0c;安装N…