关键词:
背景
在项目开发过程中,我们经常需要执行具有周期性的任务。通过定时任务可以很好的帮助我们实现。
我们拿常用的几种定时任务框架做一个比较:
从以上表格可以看出,Spring Schedule框架功能完善,简单易用。对于中小型项目需求,Spring Schedule是完全可以胜任的。
1、springboot集成schedule
1.1 添加maven依赖包
由于Spring Schedule包含在spring-boot-starter基础模块中了,所有不需要增加额外的依赖。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
1.2 启动类,添加启动注解
在springboot入口或者配置类中增加@EnableScheduling注解即可启用定时任务。
1 2 3 4 5 6 7 |
|
1.3.添加定时任务
我们将对Spring Schedule三种任务调度器分别举例说明。
1.3.1 Cron表达式
类似于Linux下的Cron表达式时间定义规则。Cron表达式由6或7个空格分隔的时间字段组成,如下图:
常用表达式:
举个栗子:
添加一个work()方法,每10秒执行一次。
注意:当方法的执行时间超过任务调度频率时,调度器会在下个周期执行。
如:假设work()方法在第0秒开始执行,方法执行了12秒,那么下一次执行work()方法的时间是第20秒。
1 2 3 4 5 6 7 |
|
1.3.2 固定间隔任务
下一次的任务执行时间,是从方法最后一次任务执行结束时间开始计算。并以此规则开始周期性的执行任务。
举个栗子:
添加一个work()方法,每隔10秒执行一次。
例如:假设work()方法在第0秒开始执行,方法执行了12秒,那么下一次执行work()方法的时间是第22秒。
1 2 3 4 |
|
1.3.3 固定频率任务
按照指定频率执行任务,并以此规则开始周期性的执行调度。
举个栗子:
添加一个work()方法,每10秒执行一次。
注意:当方法的执行时间超过任务调度频率时,调度器会在当前方法执行完成后立即执行下次任务。
例如:假设work()方法在第0秒开始执行,方法执行了12秒,那么下一次执行work()方法的时间是第12秒。
1 2 3 4 |
|
2、配置TaskScheduler线程池
在实际项目中,我们一个系统可能会定义多个定时任务。那么多个定时任务之间是可以相互独立且可以并行执行的。
通过查看org.springframework.scheduling.config.ScheduledTaskRegistrar源代码,发现spring默认会创建一个单线程池。这样对于我们的多任务调度可能会是致命的,当多个任务并发(或需要在同一时间)执行时,任务调度器就会出现时间漂移,任务执行时间将不确定。
1 2 3 4 5 6 7 |
|
2.1 自定义线程池
新增一个配置类,实现SchedulingConfigurer接口。重写configureTasks方法,通过taskRegistrar设置自定义线程池。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
3、实际应用中的问题
3.1 Web应用中的启动和关闭问题
我们知道通过spring加载或初始化的Bean,在服务停止的时候,spring会自动卸载(销毁)。但是由于线程是JVM级别的,如果用户在Web应用中启动了一个线程,那么这个线程的生命周期并不会和Web应用保持一致。也就是说,即使Web应用停止了,这个线程依然没有结束(死亡)。
解决方法:
1)当前对象是通过spring初始化
spring在卸载(销毁)实例时,会调用实例的destroy方法。通过实现DisposableBean接口覆盖destroy方法实现。在destroy方法中主动关闭线程。
1 2 3 4 5 6 7 8 9 10 |
|
2)当前对象不是通过spring初始化(管理)
那么我们可以增加一个Servlet上下文监听器,在Servlet服务停止的时候主动关闭线程。
1 2 3 4 5 6 7 |
|
3.2 分布式部署问题
在实际项目中,我们的系统通常会做集群、分布式或灾备部署。那么定时任务就可能出现并发问题,即同一个任务在多个服务器上同时在运行。
解决方法(分布式锁):
1)通过数据库表锁
2)通过缓存中间件
3)通过Zookeeper实现
总结:
spring schedule给我们提供了一套简单、快速、高效、稳定的定时任务框架。但需要考虑线程的生命周期及分布式部署问题。
玩转springboot集成篇(@scheduled静态动态定时任务)(代码片段)
publicstaticvoidmain(String[]args)SpringApplication.run(DemoApplication.class,args);privatestaticfinalLoglogger=LogFactory.getLog(DownLoadTask.class);@Scheduled(cron="00/5***?")publicvoidjustDoIt()log 查看详情
springboot整合@scheduled定时计划
SpringBoot集成了@Scheduled的相关依赖(org.springframework.scheduling.annotation.Scheduled);我们只需要直接使用即可。@Scheduled注解的使用步骤:第一步:在启动类上面启用定时任务 第二步:在要定时执行的方法上面,加上@Scheduled注解,并指... 查看详情
springboot集成quartz动态定时任务
SpringBoot自带schedule沿用的springboot少xml配置的优良传统,本身支持表达式等多种定时任务注意在程序启动的时候加上@EnableScheduling@Scheduled(cron="0/5****?")publicvoidjob()System.out.println("每五秒执行一次");为什么要... 查看详情
java程序员学深度学习djl上手2springboot集成(代码片段)
Java程序员学深度学习DJL上手2Springboot集成一、准备环境二、新建项目三、pom.xml四、源代码1.SpringBoot入口2.Controller3.application.xml五、使用方式1.运行程序:2.打开网页3.上传要识别的图片4.下载识别结果一、准备环境windowsideajdk11m... 查看详情
springboot集成quartz动态定时任务
SpringBoot自带schedule沿用的springboot少xml配置的优良传统,本身支持表达式等多种定时任务注意在程序启动的时候加上@EnableScheduling@Scheduled(cron="0/5****?")publicvoidjob()System.out.println("每五秒执行一次");为什么要... 查看详情
springboot入门:集成quartz定时任务
本片文章续《SpringBoot入门(八):集成RabbitMQ消息队列》,关于Quartz定时任务请参考《Quartz的基本使用之入门(2.3.0版本)》springboot实现定时任务,除了集成Quartz外,还可以直接使用scheduler注解。使用1个简单的注解就可以完成... 查看详情
springboot下schdule的配置与使用
...定时任务,这个时候使用定时任务就能很方便的实现。在SpringBoot中用得最多的就是Schedule。一、SpringBoot集成Schedule1、依赖配置由于Schedule就包含在spring-boot-starter中,所以无需引入其他依赖。2、启用定时任务在启动类或者配置类... 查看详情
springboot2.1.1.release集成quartz
SpringBoot2.1.1.RELEASE集成quartzhttp://www.qchcloud.cn/system/article/show/70依赖配置:<!--定时任务--><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</arti 查看详情
springboot集成quartz动态定时任务
SpringBoot集成Quartz动态定时任务项目中需要用到定时任务,考虑了下java方面定时任务无非就三种:用Java自带的timer类。稍微看了一下,可以实现大部分的指定频率的任务的调度(timer.schedule()),也可以实现关闭和开启(timer.ca... 查看详情
springboot集成quartz实现任务调度
...模式组件模式链式写法体系结构调度器任务触发器架构图springbootquartzpom配置<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</a 查看详情
springboot源码解析-----springboot精髓:集成aop
本篇主要集成Sping一个重要功能AOP我们还是先回顾一下以前Spring中是如何使用AOP的,大家可以看看我这篇文章spring5源码深度解析-----AOP的使用及AOP自定义标签Spring中使用AOP引入Aspect<dependency><groupId>org.aspectj</groupId><... 查看详情
springboot项目怎么调用深度算法
您好,springboot项目调用深度算法的具体方法如下:SpringBoot是一个快速开发的Java框架,它可以让开发者快速构建Web应用程序。深度学习算法是一种机器学习算法,它可以处理大量的数据并从中学习。要在SpringBoot项目中调用深度学... 查看详情
springboot@scheduled并发
本文介绍如何使用springboot的sheduled实现任务的定时调度,并将调度的任务实现为并发的方式。 1、定时调度配置scheduled1)注册定时任务packagecom.xiaoju.dqa.sentinel.scheduler;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframew 查看详情
springboot学习18:springboot使用scheduled定时任务器
Scheduled定时任务器:是Spring3.0以后自带的一个定时任务器。1、在pom.xml文件中添加Scheduled依赖<!--添加spring定时任务Scheduled坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context 查看详情
springboot@scheduled未生效原因
参考技术A在springboot中,支持多种定时执行模式(cron,fixRate,fixDelay),在Application或者其他Autoconfig上增加@EnableScheduling注解开启。然后在指定方法增加@Scheduled注解,如下:需要注意的是,如果在多个函数上使用了@Scheduled,那么一... 查看详情
springboot动态的配置scheduling
参考技术A一:springboot配置静态定时任务1:pom中添加依赖2:启动类中加入@EnableScheduling来开启定时任务3:@Scheduled(cron= "0/10****?")//每过10秒执行一次二: springboot动态配置定时任务:主要动态的配置。packagecom.example.... 查看详情
springboot定时任务@scheduled注解
...到使用定时器循环订单时间,然后将超时的订单状态更改.springboot的@Scheduled注解能够很快速完成我们需要的定时任务.@ComponentpublicclassExampleTimer{SimpleDateFormatdateFormat=newSimpleDateFormat("HH:mm:ss");/*每100秒执行一次*/@Schedu 查看详情
springboot@scheduled未生效原因以及相关坑
在springboot中,支持多种定时执行模式(cron,fixRate,fixDelay),在Application或者其他Autoconfig上增加@EnableScheduling注解开启。然后在指定方法增加@Scheduled注解,如下:@Scheduled(cron="000/1**?")publicvoidupdateTime(){current_log_time_appendix=s 查看详情