核心内容摘要
孙禾颐在线:连接你的精彩,点亮你的世界
文章目录
Spring Boot定时任务基础从闹钟到智能日历
1 启用定时任务功能
2 创建你的第一个定时任务
多种调度方式详解选择合适的时间管理器
1 fixedRate固定频率执行
2 fixedDelay固定延迟执行
3 cron表达式终极自定义调度
实战场景多领域应用案例
1 电商场景订单超时自动关闭
2 运维监控系统健康检查与告警
3 消息推送定时发送通知
进阶技巧让定时任务更强大
1 动态定时任务基于Nacos配置中心
2 自定义线程池避免任务阻塞
3 异常处理确保任务稳定性
Spring Boot定时任务的问题与局限性
1 单机局限分布式环境下的挑战
2 功能局限性
3 引入Quartz下一代定时任务解决方案
六、
总结与最佳实践
1 Spring Boot定时任务适用场景
2 最佳实践建议参考文章大家好我是你们的技术老友科威舟今天给大家分享一下Spring Boot的定时任务实战。
每天凌晨的数据同步、每小时的统计报表、每5分钟的状态检查……定时任务在后台开发中无处不在今天让我们一起探索Spring Boot如何化身为精准的闹钟让代码在指定时间准时工作在后台开发中定时任务就像一位忠实的助手在指定时间自动完成重要工作。
Spring Boot通过强大的Scheduled注解让定时任务开发变得简单而高效。
Spring Boot定时任务基础从闹钟到智能日历
1 启用定时任务功能在Spring Boot中启用定时任务只需在主类上添加EnableScheduling注解SpringBootApplicationEnableScheduling// 就像打开闹钟的总开关publicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}}缺少这个注解定时任务将无法执行就像忘记打开闹钟开关一样。
2 创建你的第一个定时任务ComponentpublicclassBasicScheduledTask{// 每天上午9点执行就像上班打卡Scheduled(cron0 0 9 * * ?)publicvoidmorningCheck(){System.out.println(每日检查开始newDate());}// 每5秒执行一次固定频率不停歇Scheduled(fixedRate
publicvoidheartbeatTask(){System.out.println(系统心跳检测System.currentTimeMillis());}}
多种调度方式详解选择合适的时间管理器
1 fixedRate固定频率执行fixedRate就像那个严格按时间表行事的项目管理员不管上次任务是否完成到点就开始下一次。
Scheduled(fixedRate
// 每5秒执行一次publicvoiddatabaseBackup(){// 数据库备份逻辑System.out.println(执行数据库备份newDate());}特点从上一次任务开始时间计算间隔适合执行时间稳定的任务。
2 fixedDelay固定延迟执行fixedDelay则像体贴的团队领导总是等上次任务完成后再开始计时。
Scheduled(fixedDelay
// 上次完成后延迟5秒执行publicvoidprocessDataBatch(){// 批处理逻辑执行时间不确定System.out.println(批处理完成下次执行将在5秒后);}特点从上一次任务结束时间计算间隔避免任务重叠执行。
3 cron表达式终极自定义调度cron表达式就像高级日历应用可以实现极其复杂的时间调度。
ComponentpublicclassCronScheduledTasks{// 工作日上午9点到下午6点每小时执行一次Scheduled(cron0 0
* * MON-FRI)publicvoidbusinessHourTask(){System.out.println(工作时间任务执行);}// 每月第一天凌晨2点执行Scheduled(cron0 0 2 1 * ?)publicvoidmonthlyReport(){System.out.println(生成月度报表);}}常用cron表达式参考0 0 * * * ?每小时执行0 0 0 * * ?每天凌晨执行0 0 12 * * ?每天中午12点执行0 0 10,14,16 * * ?每天10点、14点、16点执行
实战场景多领域应用案例
1 电商场景订单超时自动关闭电商系统中的经典场景——订单创建后30分钟内未支付系统自动关闭订单。
ServicepublicclassOrderTimeoutService{AutowiredprivateOrderMapperorderMapper;// 每5分钟检查一次超时订单Scheduled(cron0 */5 * * * ?)publicvoidcheckAndCloseTimeoutOrders(){System.out.println(开始检查超时订单...);ListOrdertimeoutOrdersorderMapper.selectTimeoutOrders(
;for(Orderorder:timeoutOrders){order.setStatus(OrderStatus.CLOSED);orderMapper.update(order);System.out.println(关闭超时订单order.getId());}}}
2 运维监控系统健康检查与告警ComponentpublicclassSystemHealthChecker{// 每30秒执行一次系统健康检查Scheduled(fixedRate
publicvoidsystemHealthCheck(){checkCPUUsage();checkMemoryUsage();checkDiskSpace();checkDatabaseConnection();}// 每天凌晨3点执行数据清理Scheduled(cron0 0 3 * * ?)publicvoidcleanupOldData(){System.out.println(开始清理过期数据...);// 清理30天前的日志文件// 清理临时文件等}}
3 消息推送定时发送通知ComponentpublicclassNotificationScheduler{AutowiredprivateEmailServiceemailService;// 工作日早上8点发送每日提醒Scheduled(cron0 0 8 * * MON-FRI)publicvoidsendDailyReminder(){ListUserusersuserService.findAll();for(Useruser:users){emailService.sendDailyReminder(user);}}// 每周一上午9点发送周报Scheduled(cron0 0 9 * * MON)publicvoidsendWeeklyReport(){// 生成并发送周报逻辑}}
进阶技巧让定时任务更强大
1 动态定时任务基于Nacos配置中心传统定时任务的cron表达式硬编码在代码中修改需要重新部署。
通过Nacos可以实现动态配置。
DataComponentConfigurationProperties(prefixtask-schedule)publicclassTaskProperties{privateStringorderCheckCron0 */5 * * * ?;}ComponentpublicclassDynamicScheduledTask{AutowiredprivateTaskPropertiestaskProperties;// 使用SpEL表达式从配置类读取cron表达式Scheduled(cron#{taskProperties.orderCheckCron})publicvoiddynamicOrderCheck(){// 订单检查逻辑}}
2 自定义线程池避免任务阻塞默认情况下Spring Boot使用单线程执行所有定时任务可能导致任务阻塞。
ConfigurationpublicclassSchedulerConfigimplementsSchedulingConfigurer{OverridepublicvoidconfigureTasks(ScheduledTaskRegistrartaskRegistrar){ThreadPoolTaskSchedulerschedulernewThreadPoolTaskScheduler();scheduler.setPoolSize(
;// 设置线程池大小scheduler.setThreadNamePrefix(scheduled-task-);scheduler.setWaitForTasksToCompleteOnShutdown(true);scheduler.setAwaitTerminationSeconds(
;scheduler.initialize();taskRegistrar.setTaskScheduler(scheduler);}}
3 异常处理确保任务稳定性定时任务中的异常如果处理不当可能导致任务终止。
ComponentpublicclassRobustScheduledTask{Scheduled(fixedRate
// 每分钟执行一次publicvoidrobustTask(){try{// 可能抛出异常的业务逻辑processBusinessLogic();}catch(Exceptione){// 记录异常日志但任务会继续执行System.err.println(任务执行失败但不会影响下次执行: e.getMessage());// 发送告警通知alertService.sendAlert(e);}}}
Spring Boot定时任务的问题与局限性尽管Spring Boot定时任务非常强大但在某些场景下存在明显局限性。
1 单机局限分布式环境下的挑战在集群部署环境中每个节点都会执行相同的定时任务导致任务重复执行。
解决方案尝试基于Redis分布式锁ComponentpublicclassDistributedScheduledTask{AutowiredprivateStringRedisTemplateredisTemplate;Scheduled(cron0 0 2 * * ?)publicvoiddistributedDataCleanup(){// 尝试获取分布式锁有效期10分钟BooleanlockedredisTemplate.opsForValue().setIfAbsent(data-cleanup-lock,locked,10,TimeUnit.MINUTES);if(locked!nulllocked){try{// 获取锁成功执行任务performDataCleanup();}finally{// 释放锁redisTemplate.delete(data-cleanup-lock);}}else{System.out.println(任务已在其他节点执行本节点跳过);}}}
2 功能局限性Spring Boot内置定时任务还存在以下限制任务持久化服务重启后会丢失任务执行状态任务动态管理无法在运行时动态添加、修改、删除任务监控与管理缺乏完善的任务执行监控界面失败重试任务执行失败后缺乏自动重试机制
3 引入Quartz下一代定时任务解决方案正是由于这些局限性在复杂的企业级应用场景中我们通常需要更强大的调度框架——Quartz。
Quartz提供了以下高级特性分布式调度支持集群部署避免任务重复执行任务持久化将任务信息存储到数据库服务重启不丢失动态管理支持运行时动态添加、修改、删除任务故障转移当节点故障时任务自动转移到其他节点丰富的监控提供完善的管理界面和监控指标// Quartz示例预览publicclassQuartzJobExampleimplementsJob{Overridepublicvoidexecute(JobExecutionContextcontext){// 复杂的任务逻辑System.out.println(Quartz任务执行newDate());}}
六、
总结与最佳实践
1 Spring Boot定时任务适用场景Spring Boot内置定时任务非常适合以下场景单体应用非集群部署的应用简单任务执行时间短、逻辑简单的任务开发测试快速原型开发和测试环境非关键业务对执行可靠性要求不高的业务
2 最佳实践建议异常处理确保任务异常不会影响后续执行日志记录详细记录任务执行情况便于排查问题资源配置根据任务数量和复杂度配置合适的线程池幂等设计确保任务可重复执行而不会产生副作用监控告警建立任务执行监控和失败告警机制Spring Boot定时任务就像一位忠实的助手在恰当的时机自动完成工作。
但对于复杂的生产环境这位助手可能需要升级为更专业的任务管理专家——这就是我们下一章要介绍的Quartz定时任务框架。
参考文章https://bbs.huaweicloud.com/blogs/456470https://www.qcloud.com/developer/article/2437423https://blog.csdn.net/2402_85302906/article/details/155689625https://blog.csdn.net/aakhvb/article/details/151372484https://docs.pingcode.com/ask/ask-ask/
htmlhttps://m.jb
net/program/353051qq
htmhttps://blog.csdn.net/weixin_45737215/article/details/146576250https://blog.51cto.com/u_16213421/12785327https://blog.51cto.com/u_16213425/12561995本文主要观点基于以上参考资料结合实际开发经验整理而成。
转载请注明出处。
*更多技术干货欢迎关注微信公众号科威舟的AI笔记~【转载须知】转载请注明原文出处及作者信息