【Springboot知识】Springboot计划任务Schedule详解

文章目录

  • Spring Boot 定时任务从原理到实现详解
    • 一、核心原理分析
      • 1. 架构分层
      • 2. 核心组件
      • 3. 线程模型
    • 二、基础实现步骤
      • 1. 添加依赖
      • 2. 主类配置
      • 3. 定时任务类
    • 三、高级配置技巧
      • 1. 自定义线程池
      • 2. 动态配置参数
      • 3. 分布式锁集成(Redis示例)
    • 四、异常处理机制
      • 1. 统一异常处理器
      • 2. 任务重试机制
    • 五、监控与调试
      • 1. Actuator 端点
      • 2. 性能监控
    • 六、完整示例项目结构
    • 七、最佳实践建议
    • Schedule注解参数详细说明
      • 一、注解基础参数详解
        • 1. 核心参数配置
        • 2. 参数对照表
      • 二、Cron表达式详解
        • 1. 标准格式
        • 2. 特殊字符说明
        • 3. 常用表达式示例
      • 三、多模式配置示例
        • 1. 基础模式组合
        • 2. 动态参数注入
      • 四、高级使用技巧
        • 1. 多任务并行执行
        • 2. 条件化调度
        • 3. 分布式锁集成
      • 五、异常处理机制
        • 1. 自定义异常处理器
        • 2. 重试机制
      • 六、常见问题解决方案
        • 1. 任务不执行排查
        • 2. 多实例重复执行
      • 七、最佳实践建议

Spring Boot 定时任务从原理到实现详解

一、核心原理分析

1. 架构分层

graph TDA[Application] --> B[@EnableScheduling]B --> C[ScheduledAnnotationBeanPostProcessor]C --> D[TaskScheduler]D --> E[ThreadPoolTaskScheduler]D --> F[ConcurrentTaskScheduler]

2. 核心组件

  • @EnableScheduling:启用定时任务自动配置
  • ScheduledAnnotationBeanPostProcessor:解析@Scheduled注解
  • TaskScheduler:任务调度接口
  • CronTrigger:处理cron表达式

3. 线程模型

// 默认线程池配置
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupportimplements TaskScheduler, SchedulingTaskExecutor {private volatile int poolSize = 1; // 默认单线程private ThreadFactory threadFactory = new CustomizableThreadFactory("task-scheduler-");
}

二、基础实现步骤

1. 添加依赖

<!-- pom.xml -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency>

2. 主类配置

@SpringBootApplication
@EnableScheduling
public class SchedulingApplication {public static void main(String[] args) {SpringApplication.run(SchedulingApplication.class, args);}
}

3. 定时任务类

@Component
public class ScheduledTasks {private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);// 固定频率(任务开始时间间隔)@Scheduled(fixedRate = 5000)public void fixedRateTask() {log.info("Fixed Rate Task :: Execution Time - {}", LocalDateTime.now());}// 固定延迟(任务结束时间间隔)@Scheduled(fixedDelay = 7000, initialDelay = 2000)public void fixedDelayTask() {log.info("Fixed Delay Task :: Execution Time - {}", LocalDateTime.now());}// Cron表达式@Scheduled(cron = "0 0/15 9-17 * * MON-FRI")public void cronTask() {log.info("Cron Task :: Execution Time - {}", LocalDateTime.now());}
}

三、高级配置技巧

1. 自定义线程池

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();taskScheduler.setPoolSize(5);taskScheduler.setThreadNamePrefix("custom-scheduler-");taskScheduler.initialize();taskRegistrar.setTaskScheduler(taskScheduler);}
}

2. 动态配置参数

application.properties
schedule.rate=10000
schedule.delay=5000
schedule.cron=0 0 8 * * *
@Scheduled(fixedRateString = "${schedule.rate}")
public void dynamicRateTask() {// ...
}@Scheduled(cron = "${schedule.cron}")
public void dynamicCronTask() {// ...
}

3. 分布式锁集成(Redis示例)

@Scheduled(fixedRate = 10000)
public void distributedTask() {String lockKey = "scheduledTaskLock";String requestId = UUID.randomUUID().toString();try {if (redisLockUtil.tryGetLock(lockKey, requestId, 30)) {log.info("Acquired lock, executing task...");// 业务逻辑}} finally {redisLockUtil.releaseLock(lockKey, requestId);}
}

四、异常处理机制

1. 统一异常处理器

@ControllerAdvice
public class SchedulingExceptionHandler {@ExceptionHandler(TaskExecutionException.class)public void handleTaskException(TaskExecutionException ex) {log.error("Scheduled task failed: {}", ex.getMessage());// 发送告警通知}
}

2. 任务重试机制

@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))
@Scheduled(fixedRate = 5000)
public void retryableTask() {// 可能失败的业务逻辑if (Math.random() > 0.5) {throw new RuntimeException("Simulated error");}
}

五、监控与调试

1. Actuator 端点

management.endpoints.web.exposure.include=scheduledtasks

访问 /actuator/scheduledtasks 查看任务列表:

{"cron": [{"runnable": {"target": "com.example.ScheduledTasks.cronTask"},"expression": "0 0/15 9-17 * * MON-FRI"}]
}

2. 性能监控

@Scheduled(fixedRate = 5000)
@Timed(value = "scheduled.task", description = "监控任务执行时间")
public void monitoredTask() {// 业务逻辑
}

六、完整示例项目结构

scheduling-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/
│   │   │       ├── config/
│   │   │       │   └── SchedulerConfig.java
│   │   │       ├── ScheduledTasks.java
│   │   │       └── SchedulingApplication.java
│   │   └── resources/
│   │       ├── application.properties
│   │       └── logback-spring.xml
│   └── test/
└── pom.xml

七、最佳实践建议

  1. 线程池配置原则

    # 推荐线程数 = CPU核心数 * 2(IO密集型)
    # 推荐线程数 = CPU核心数 + 1(计算密集型)
    
  2. 任务设计规范

    • 单任务执行时间 < 调度间隔时间
    • 添加事务边界控制
    • 避免任务间状态共享
  3. 生产环境注意事项

    // 添加健康检查
    @Component
    public class ScheduleHealthIndicator implements HealthIndicator {@Overridepublic Health health() {// 检查任务最后执行时间return Health.up().build();}
    }
    

通过以上配置和实现,可以构建出高可靠、易维护的定时任务系统。定时任务的执行频率需要根据实际业务需求进行合理设置,同时要特别注意在分布式环境下的任务协调问题。

Schedule注解参数详细说明

一、注解基础参数详解

1. 核心参数配置
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {String cron() default "";String zone() default "";long fixedDelay() default -1;String fixedDelayString() default "";long fixedRate() default -1;String fixedRateString() default "";long initialDelay() default -1;String initialDelayString() default "";
}
2. 参数对照表
参数名称类型必填默认值说明
cronString“”Unix风格的cron表达式
zoneString“”时区ID(如"Asia/Shanghai")
fixedDelaylong-1上次执行结束到下次执行的间隔(毫秒)
fixedDelayStringString“”支持占位符的字符串形式(如"${schedule.delay}")
fixedRatelong-1固定频率执行(毫秒)
fixedRateStringString“”支持占位符的字符串形式
initialDelaylong-1首次执行的延迟时间(毫秒)
initialDelayStringString“”支持占位符的字符串形式

二、Cron表达式详解

1. 标准格式
秒(0-59) 分(0-59) 时(0-23) 日(1-31) 月(1-12) 周(0-7) 年(可选)
2. 特殊字符说明
字符含义示例说明
*任意值0 * * * * *每分钟0秒执行
?不指定(仅日/周字段)0 0 0 ? * MON每周一0点执行
-范围0 0 9-17 * * *每天9点到17点整点执行
,多个值0 0 8,12,18 * * *每天8、12、18点执行
/间隔频率0 0/15 * * * *每15分钟执行一次
L最后一天/最后一周0 0 0 L * ?每月最后一天0点执行
W最近工作日0 0 0 LW * ?每月最后一个工作日执行
#第几个周几0 0 0 ? * 5#2每月第2个周四执行
3. 常用表达式示例
@Scheduled(cron = "0 0 3 * * ?")      // 每天凌晨3点执行
@Scheduled(cron = "0 0/5 9-17 * * MON-FRI") // 工作日9-17点每5分钟执行
@Scheduled(cron = "0 0 12 1 * ?")    // 每月1号中午12点执行
@Scheduled(cron = "0 0 8 L * ?")      // 每月最后一天上午8点执行

三、多模式配置示例

1. 基础模式组合
// 初始延迟3秒,之后每5秒执行
@Scheduled(initialDelay = 3000, fixedRate = 5000) // 每天8:30执行(使用属性配置)
@Scheduled(cron = "${app.schedule.daily-report}") 
2. 动态参数注入
application.properties
schedule.interval=5000
schedule.initial.delay=10000
schedule.cron.expression=0 0/15 * * * *
@Scheduled(fixedRateString = "${schedule.interval}",initialDelayString = "${schedule.initial.delay}"
)
public void dynamicScheduleTask() {// 业务逻辑
}@Scheduled(cron = "${schedule.cron.expression}")
public void cronTask() {// 定时任务
}

四、高级使用技巧

1. 多任务并行执行
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(5);scheduler.setThreadNamePrefix("schedule-pool-");scheduler.initialize();taskRegistrar.setTaskScheduler(scheduler);}
}
2. 条件化调度
@Profile("production")  // 仅生产环境生效
@ConditionalOnProperty(name = "scheduler.enabled", havingValue = "true")
@Scheduled(fixedRate = 10000)
public void conditionalTask() {// 生产环境专用任务
}
3. 分布式锁集成
@Scheduled(cron = "0 0/30 * * * ?")
public void distributedTask() {String lockKey = "reportGenerationLock";try {if (redisLock.tryLock(lockKey, 300)) { // 获取30秒锁generateReport();}} finally {redisLock.release(lockKey);}
}

五、异常处理机制

1. 自定义异常处理器
@ControllerAdvice
public class ScheduleExceptionHandler {@ExceptionHandler(ScheduleExecutionException.class)public void handleScheduleException(ScheduleExecutionException ex) {log.error("定时任务执行失败: {}", ex.getMessage());// 发送告警通知alertService.sendAlert("Schedule Failure", ex.getMessage());}
}
2. 重试机制
@Retryable(value = {DataAccessException.class},maxAttempts = 3,backoff = @Backoff(delay = 1000, multiplier = 2)
)
@Scheduled(fixedDelay = 5000)
public void retryableTask() {// 可能失败的数据操作databaseService.batchUpdate();
}

六、常见问题解决方案

1. 任务不执行排查
1. 检查主类是否添加`@EnableScheduling`
2. 确认任务方法为`public`修饰
3. 验证cron表达式有效性(可用在线验证工具)
4. 检查线程池是否被占满(默认单线程)
2. 多实例重复执行
// 使用数据库锁方案示例
@Transactional
@Scheduled(cron = "0 0 3 * * ?")
public void exclusiveTask() {LocalDateTime now = LocalDateTime.now();ScheduleLock lock = lockRepo.findByTaskName("dailyCleanup");if (lock == null || lock.getLockUntil().isBefore(now)) {// 获取锁(设置30分钟有效期)lockRepo.save(new ScheduleLock("dailyCleanup", now.plusMinutes(30)));// 执行任务dataCleanupService.cleanup();// 释放锁lockRepo.deleteById("dailyCleanup");}
}

七、最佳实践建议

  1. 线程池配置原则

    # 推荐配置公式
    IO密集型任务:线程数 = CPU核心数 * 2
    计算密集型任务:线程数 = CPU核心数 + 1
    
  2. 执行时间监控

    @Scheduled(fixedRate = 60000)
    public void monitoredTask() {StopWatch watch = new StopWatch();try {watch.start();// 业务逻辑} finally {watch.stop();if (watch.getTotalTimeMillis() > 5000) {log.warn("任务执行超时: {}ms", watch.getTotalTimeMillis());}}
    }
    
  3. 重要任务日志规范

    @Scheduled(cron = "0 0 2 * * ?")
    public void criticalTask() {log.info("==== 开始执行数据归档任务 ====");try {archiveService.archiveData();log.info("数据归档成功,归档数量: {}", count);} catch (Exception e) {log.error("数据归档失败", e);throw e;} finally {log.info("==== 结束数据归档任务 ====");}
    }
    

通过合理配置和遵循最佳实践,可以构建出高可靠、易维护的定时任务系统。特别注意在分布式环境下做好任务协调,避免重复执行导致的数据不一致问题。

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

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

相关文章

MySQL:联合查询

目录 一、笛卡尔积 ​二、内连接 三、外连接 &#xff08;1&#xff09;左外连接 &#xff08;2&#xff09;右外连接 &#xff08;3&#xff09;全外连接 四、自连接 五、子查询 &#xff08;1&#xff09;单行子查询 &#xff08;2&#xff09;多行子查询 &…

深入理解 Cortex-M3 的内核寄存器组

每个 MCU 开发工程师一定都了解寄存器这个东西&#xff0c;以 STM32 为例&#xff0c;其拥有非常多的外设模块&#xff0c;如串口、SPI、IIC 等等&#xff0c;如果要使用这些外设&#xff0c;使其按照我们的要求工作&#xff0c;就需要配置这些外设的寄存器&#xff0c;往这些寄…

网络安全自动化:找准边界才能筑牢安全防线

数字时代&#xff0c;企业每天要面对成千上万的网络攻击。面对庞大的服务器群、分散的团队和长期不重启的设备&#xff0c;很多企业开始思考&#xff1a;哪些安全操作适合交给机器自动处理&#xff1f;哪些必须由人工把关&#xff1f;今天我们就用大白话聊聊这件事。 一、这些事…

C++负载均衡远程调用学习之负载均衡算法与实现

目录 01 lars 系统架构回顾 02 lars-lbAgentV0.4-route_lb处理report业务流程 03 lars-lbAgentV0.4-负责均衡判断参数配置 04 lars-lbAgentV0.4-负载均衡idle节点的失败率判断 05 lars-lbAgentV0.4-负载均衡overload节点的成功率判断 06 lars-lbAgentV0.4-负载均衡上报提交…

领略算法真谛: 多源bfs

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…

雷电模拟器-超好用的Windows安卓模拟器

一、雷电模拟器介绍 雷电模拟器是一款功能强大的软件&#xff0c;它能够在电脑上模拟出安卓手机系统&#xff0c;让你可以在电脑上运行各类手机应用及游戏。其采用虚拟安卓手机操作界面&#xff0c;为玩家带来了独特的体验。 &#xff08;一&#xff09;强大的兼容性 雷电模拟…

文章三《机器学习基础概念与框架实践》

文章3:机器学习基础概念与框架实践 ——从理论到代码,用Scikit-learn构建你的第一个分类模型 一、机器学习基础理论:三大核心类型 机器学习是人工智能的核心,通过数据让计算机自动学习规律并做出预测或决策。根据学习方式,可分为三类: 1. 监督学习(Supervised Learni…

脑机接口技术:开启人类与机器的全新交互时代

在科技飞速发展的今天&#xff0c;人类与机器的交互方式正经历着前所未有的变革。从最初的键盘鼠标&#xff0c;到触摸屏&#xff0c;再到语音控制&#xff0c;每一次交互方式的升级都极大地提升了用户体验和效率。如今&#xff0c;脑机接口&#xff08;Brain-Computer Interfa…

8.2 GitHub企业级PDF报告生成实战:ReportLab高级技巧与性能优化全解析

GitHub企业级PDF报告生成实战:ReportLab高级技巧与性能优化全解析 GitHub Sentinel 高级功能实现:PDF 报告生成技术详解 关键词:PDF 报告生成, ReportLab 实战, 结构化数据转换, 容器化字体配置, 企业级报告模板 1. 需求分析与技术选型 PDF 报告生成需要满足以下技术要求…

架构思维:构建高并发读服务_基于流量回放实现读服务的自动化测试回归方案

文章目录 引言一、升级读服务架构&#xff0c;为什么需要自动化测试&#xff1f;二、自动化回归测试系统&#xff1a;整体架构概览三、日志收集1. 拦截方式2. 存储与优化策略3. 架构进化 四、数据回放技术实现关键能力 五、差异对比对比方式灵活配置 六、三种回放模式详解1. 离…

基于Spring Boot 3.0、ShardingSphere、PostgreSQL或达梦数据库的分库分表

要实现基于Spring Boot 3.0、ShardingSphere、PostgreSQL或达梦数据库的分库分表&#xff0c;首先需要对ShardingSphere进行一些基本配置。你提到的溯源码、批次号等数据需要考虑到跨年数据的存储&#xff0c;因此要设计一个能够动态扩展的分表策略 添加ShardingSphere依赖 在…

位运算的应用

1. 判断偶数&#xff0c;判断最低位是0还是1即可&#xff0c;⽐求模快 x % 2 ! 0 //x正负都可以判断&#xff1b;不⽤x%2 1&#xff0c;因为如果x为负奇数&#xff0c;x%2-1 (x & 0x1) 0 例如&#xff1a; int x; int main() { cin>>x; if((x & 0x1)0) cout<…

FOC算法开环控制基础

1. 为什么要有FOC算法 先看看从有刷电机到无刷电机的简单介绍&#xff0c;如下图1&#xff0c;通电螺线圈会产生磁场&#xff0c;这个磁场会产生N级和S级&#xff0c;然后这个电磁铁就可以吸引永磁体&#xff0c;S级吸引N级&#xff0c;N级吸引S级&#xff0c;通俗的来说&…

【计算机网络】HTTP中GET和POST的区别是什么?

从以下几个方面去说明&#xff1a; 1.定义 2.参数传递方式 3.安全性 4.幂等性 1.定义&#xff1a; GET&#xff1a; 获取资源&#xff0c;通常请求数据而不改变服务器的状态。POST&#xff1a; 提交数据到服务器&#xff0c;通常会改变服务器的状态或副作用(如创建或更新资源…

7400MB/s5050TBW完美结合,全新希捷酷玩530R SSD体验评测

7400MB/s&5050TBW完美结合&#xff0c;全新希捷酷玩530R SSD体验评测 哈喽小伙伴们好&#xff0c;我是Stark-C~ 说到希捷酷玩530 SSD&#xff0c;很多硬核进阶玩家应该都知道&#xff0c;或者说正在使用&#xff08;比如说我~&#xff09;。 作为希捷大厂旗下高性能SSD的…

(undone) MIT6.S081 2023 学习笔记 (Day11: LAB10 mmap)

url: https://pdos.csail.mit.edu/6.1810/2023/labs/mmap.html mmap和munmap系统调用允许UNIX程序对其地址空间进行精细控制。它们可用于进程间共享内存、将文件映射到进程地址空间&#xff0c;并作为用户级页面错误处理方案的一部分&#xff0c;例如课程中讨论的垃圾回收算法。…

Q_OBJECT宏的作用

Qt 中&#xff0c;如果一个类中定义了信号&#xff08;signals&#xff09;或槽&#xff08;slots&#xff09;&#xff0c;那么这个类必须包含 Q_OBJECT 宏。 Q_OBJECT宏是 Qt 元对象系统的核心部分&#xff0c;它使得信号和槽机制能够正常工作。 Q_OBJECT宏是 Qt 的元对象系统…

信息安全基石:加解密技术的原理、应用与未来

信息加解密技术是信息安全领域的核心技术之一&#xff0c;以下为你详细介绍&#xff1a; 一、加密技术 1.定义&#xff1a;加密是通过特定的算法和密钥&#xff0c;将原始的明文信息转化为看似无意义的密文信息的过程。这一过程使得信息在传输、存储等过程中&#xff0c;即使…

LeetCode:返回倒数第k个结点

1、题目描述 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回该节点的值。 注意&#xff1a;本题相对原题稍作改动 示例&#xff1a; 输入&#xff1a; 1->2->3->4->5 和 k 2 输出&#xff1a; 4 说明&#xff1a; 给定的 k 保证是有效的。 2、…

R004 -计算机硬件基础

目录 1.数据表示&计算机网络组成 2.计算机网络分类 3.冯诺依曼体系结构 4.指令系统基础 5.指令系统类型 6.流水线技术 流水线周期 &#xff1a;各流水段中&#xff0c;执行时间最长的那一段。就是T 流水线时间&#xff1a;t 1t2t 3 (n-1) * T 7.流水线指标 8.存储系…