当前位置: 首页 > java >正文

【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.xdnf.cn/news/4065.html

相关文章:

  • 前端懒加载(Lazy Loading)实战指南
  • 旋转图像(中等)
  • RPC是什么
  • Linux文件复制命令精要指南:cp与scp详解
  • Three.js + React 实战系列 - 客户评价区细解教程 Clients 组件✨(回答式评价 + 评分星级)
  • 51c大模型~合集124
  • TS 类型兼容性
  • 乡村饮用水厂无线网络规划与设计:融合 LoRaWAN、5G、Mesh 的分层异构方案
  • unity TMP字体使用出现乱码方框
  • 最长回文子串(动规 + 中心拓展)
  • 反转字符串2
  • 杰理-JL701-充电开机,芯片不进入休眠
  • Spring Boot 中 @Bean 注解详解:从入门到实践
  • 无人机 | 无人机设计概述
  • Springclound常用五大组件及其使用原理
  • 防止交叉验证中的数据泄露:提升模型在实际环境中的性能
  • 怎样获得真实带宽之宽带升级后
  • 014枚举之指针尺取——算法备赛
  • C++类与对象深度解析:从基础到应用
  • kotlin 01flow-StateFlow 完整教程
  • Python-numpy中ndarray对象创建,数据类型,基本属性
  • 【免费分享无广告】刷视频助手抖音快手小红书视频号自动脚本刷视频养号
  • 前端面试每日三题 - Day 25
  • Netty的内存池机制怎样设计的?
  • 专业化婴幼儿托育服务与管理实训室建设方案
  • Easy云盘总结篇-回收站
  • 组合两个表 --- MySQL [Leetcode 题目详解]
  • 备战全国信息素养大赛 图形化挑战赛——约数和
  • “公共类 XXX 应该在文件中出现”错误怎么查找解决
  • 项目管理学习-CSPM(1)