宝哥软件园

对java中Spring任务计时任务的深刻理解

编辑:宝哥软件园 来源:互联网 时间:2021-09-03

对java中Spring任务计时任务的深刻理解

在工作中,spring任务被用作定时任务的处理,并且spring通过接口TaskExecutor和TaskScheduler为异步定时任务提供了一个抽象。这意味着spring允许您使用其他定时任务框架。当然,spring本身也提供了一个定时任务的实现:spring task。Spring task支持线程池,可以高效处理很多不同的定时任务。同时,spring还支持使用Java内置的Timer定时器和Quartz计时框架。由于篇幅有限,这里只介绍弹簧任务的使用。

实际上,官方文件已经介绍得足够详细,只有英文版。因此,为了更好地理解和使用spring task,首先简单介绍spring task的实现原理,然后用实际代码演示如何使用spring task。这里将涉及一个非常重要的知识点:cron表达式。

任务执行器和任务计划程序

TaskExecutor是spring task的第一个抽象,这自然会让人联想到jdk中并发包下的Executor。事实上,引入TaskExecutor是为了区别于Executor,引入TaskExecutor的目的是为定时任务的执行提供线程池支持。那么,问题来了,为什么spring不直接使用jdk自带的Executor呢?TaskExecutor源代码如下?

公共接口TaskExecutor扩展了Executor { void execute(Runnable var1);}那么,答案显而易见。TaskExecutor提供的线程池支持也是基于jdk自己的Executor。在Executor中使用也没什么不同。

TaskScheduler是spring task的第二个抽象,所以从字面上来说,TaskScheduler就是为调度的任务提供支持。TaskScheduler需要传入一个Runnable任务作为参数,并指定要定期执行的时间或触发器,这样就可以定期执行Runnable任务。引入时间很容易理解,引入触发器很有趣。因为这里需要cron表达式来触发定时任务,所以首先要了解cron表达式的用法。

spring 4.x不再支持7个参数的Cronin表达式,要求是6个参数(后面会介绍哪个参数)。cron表达式的格式如下:

{秒} {分} {小时} {日期(具体日期)} {月} {周}秒:必选,允许值范围为0-59,支持的特殊符号包括,-*/,表示仅在某一秒内触发任务,-表示在某一时间段内触发任务,*表示每秒触发一次,/哪一分:必选,允许值范围为0-59,支持的特殊符号与秒相同。当含义类比:必选,允许值范围为0-23,支持的特殊符号与秒相同,含义类比日期:必选,允许值范围为1-31,支持的特殊符号大于秒?这意味着它与{week}是互斥的,这意味着如果明确指定{week}触发器,{date}就没有意义,以免冲突和混淆。月:必选,允许值范围为1-12(JAN-DEC),支持的特殊符号与秒相同,表示周;必选,允许值范围为1~7 (SUN-SAT),1代表周日(一周的第一天),以此类推,7代表周六,支持的符号大于秒?所表达的含义与{date}互斥,这意味着如果{date}被明确指定为触发器,{week}就没有意义。例如,以下cron表达式:

//表达的意思是:每半分钟触发任务一次30 * * * *?Spring提供了一个CronTrigger。通过传入一个Runnable任务和CronTrigger,可以使用cron表达式来指定定时任务。很重要吗?实际上,cron表达式在工程实践中也被广泛使用。事实上,执行了以下代码:

scheduler.schedule(任务,新的CronTrigger('30 * * * *?)));任务计划程序抽象的好处是让需要执行定时任务的代码不需要指定特定的定时框架(比如计时器和石英).任务计划程序的更简单的实现是线程池任务计划程序,它实际上代理一个jdk中的调度任务执行器,并且也实现了任务执行者接口,所以需要经常执行定时任务的场景可以使用这个实现(春天推荐)。我们再来看一下任务执行者和任务计划程序的类继承关系:

通常而言,使用春季任务实现定时任务有两种方式:注解和可扩展标记语言配置文件。这里使用可扩展标记语言配置文件的方式加以说明。

实战

创建专家工程,pom.xml:

?可扩展标记语言版本='1.0 '编码='UTF-8 '?项目xmlns=' http://aven。阿帕奇。org/POM/4。0 .0 ' xmlns : xsi=' http://www。w3。org/2001/XMLSchema-instance ' xsi 3360 schema location=' http://aven。阿帕奇。org/POM/4。0 .0 http://maven.apache.org/xsd/maven-4.0.0.xsd'模型版本4 .0 .0/模型版本groupIdcom.rhwayfun/groupId人工智能-任务-演示/人工智能版本1.0-快照开发需要执行定时任务的方法:

打包。rhwayfun。任务;导入组织。弹簧框架。刻板印象。组件;导入Java。时间到了。LocalDatetime/* * * @作者仲* * @日期2016年09月10日14:30 * @描述*/@组件公共类app { public void execute 1(){ system。出去。printf('任务:% s,当前时间: %sn ',1,本地日期时间。now());} public void execute 2(){ system。出去。printf('任务:% s,当前时间: %sn ',2,本地日期时间。now());} public void execute 3(){ system。出去。printf('任务:% s,当前时间: %sn ',3,本地日期时间。now());} public void execute 4(){ system。出去。printf('任务:% s,当前时间: %sn ',4,本地日期时间。now());} public void execute 5(){ system。出去。printf('任务:% s,当前时间: %sn ',5,本地日期时间。now());} public void execute 6(){ system。出去。printf('任务:% s,当前时间: %sn ',6,本地日期时间。now());} public void execute 7(){ system。出去。printf('任务:% s,当前时间: %sn ',7,本地日期时间。now());} public void execute 8(){ system。出去。printf('任务:% s,当前时间: %sn ',8,本地日期时间。now());} public void execute 9(){ system。出去。printf('任务:% s,当前时间: %sn ',9,本地日期时间。now());} public void execute 10(){ system。出去。printf('任务:% s,当前时间: %sn ',10,本地日期时间。now());} public void execute 11(){ system。出去。printf('任务:% s,当前时间: %sn ',11,本地日期时间。now());} }春天配置文件如下:

?可扩展标记语言版本='1.0 '编码='UTF-8 '?beans xmlns=' http://www。弹簧框架。org/schema/beans ' xmlns : xsi=' http://www .w3。org/2001/XMLSchema-instance ' xmlns : context=' http://www .弹簧框架。org/schema/context ' xmlns 3: task=' http://www .弹簧框架。org/schema/task ' xsi : schema location=' http://www.springframework.org/schema/beans 33http://www。-配置注解扫描-context :组件-扫描基本包=' com。rhwayfun。任务/任务:调度程序id=' Taskscheduler '池大小=' 100 '/任务:已调度-任务调度程序=' Taskscheduler '!-每半分钟触发任务-任务:计划的ref=' app '方法=' execute 1 ' cron=' 30 * * * *?'/!-每小时的10分30秒触发任务-任务:计划的ref=' app '方法=' execute 2 ' cron=' 30 10 * * *?'/!-每天一点10分30秒触发任务-任务:计划的ref=' app '方法=' execute 3 ' cron=' 30 10 1 * *?'/!-每月20号的一点10分30秒触发任务-任务:计划的ref=' app '方法=' execute 4 ' cron=' 30 10 1 20 *?'/!-每年10月20号的一点10分30秒触发任务-任务:计划的ref=' app '方法=' execute 5 ' cron=' 30 10 1 20 10 '?/!-每15秒、30秒、45秒时触发任务-任务:计划的ref=' app '方法=' execute 6 ' cron=' 15,30,45 * * * *?'/!- 15秒到45秒每隔一秒触发任务-任务:计划的ref=' app '方法=' execute 7 ' cron=' 15-45 * * * *?'/!-每分钟的每15秒时任务任务,每隔5秒触发一次-任务:计划的ref=' app '方法=' execute 8 ' cron=' 15/5 * * * *?'/!-每分钟的15到30秒之间开始触发,每隔5秒触发一次-任务:计划的ref=' app '方法=' execute 9 ' cron=' 15-30/5 * * * *?'/!-每小时的0分0秒开始触发,每隔3分钟触发一次-任务:计划的ref=' app '方法=' execute 10 ' cron=' 0 0/3 * * *?'/!-星期一到星期五的10点15分0秒触发任务-任务:计划的ref=' app '方法=' execute 11 ' cron=' 0 15 10?* MON-FRI '/任务:s计划任务/bean编写测试代码:

打包。rhwayfun。任务;导入组织。弹簧框架。语境。应用程序上下文;导入组织。弹簧框架。语境。支持。classpathsmlapplicationcontext/* * * @作者仲* * @日期2016年09月10日14:55 * @ description */public class AppTest { public static void main(String[]args){ application context=new class path xmlaplicationcontext(' class path :/app-context-task。XML ');}}运行测试代码,控制台会定时输出每个定时任务的日志信息,说明测试通过。

小插曲

由于项目使用jdk 1.8进行开发,所以初始的时候每次砰的一声文件发生修改,编译器的版本又变成了jdk 1.5,后面发现需要在砰的一声文件中添加建设便签那部分才能将默认的编译器进行修改。也算一个小收获了。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

更多资讯
游戏推荐
更多+