深入浅出spring task定时任务

在工作中有用到spring task作为定时任务的处理,spring通过接口TaskExecutorTaskScheduler这两个接口的方式为异步定时任务提供了一种抽象。这就意味着spring容许你使用其他的定时任务框架,当然spring自身也提供了一种定时任务的实现:spring task。spring task支持线程池,可以高效处理许多不同的定时任务。同时,spring还支持使用Java自带的Timer定时器和Quartz定时框架。限于篇幅,这里将只介绍spring task的使用。

其实,官方文档已经介绍地足够详细,只不过都是英文版,所以为了更好地理解并使用spring task,首先会对spring task的实现原理做一个简单的介绍,然后通过实际代码演示spring task是如何使用的。这里会涉及到一个很重要的知识点:cron表达式。

TaskExecutor和TaskScheduler

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

  1. public interface TaskExecutor extends Executor {
  2. void execute(Runnable var1);
  3. }

那么,答案很显然,TaskExecutor提供的线程池支持也是基于jdk自带的Executor的。用法于Executor没有什么不同。

TaskScheduler是spring task的第二个抽象,那么从字面的意义看,TaskScheduler就是为了提供定时任务的支持咯。TaskScheduler需要传入一个Runnable的任务做为参数,并指定需要周期执行的时间或者触发器,这样Runnable任务就可以周期性执行了。传入时间很好理解,有意思的是传入一个触发器(Trigger)的情况,因为这里需要使用cron表达式去触发一个定时任务,所以有必要先了解下cron表达式的使用。

在spring 4.x中已经不支持7个参数的cronin表达式了,要求必须是6个参数(具体哪个参数后面会说)。cron表达式的格式如下:

  1. {秒} {分} {时} {日期(具体哪天)} {月} {星期}
  • 秒:必填项,允许的值范围是0-59,支持的特殊符号包括 
    ,
     - * /,表示特定的某一秒才会触发任务,-表示一段时间内会触发任务,*表示每一秒都会触发,/表示从哪一个时刻开始,每隔多长时间触发一次任务。
  • 分:必填项,允许的值范围是0-59,支持的特殊符号和秒一样,含义类推
  • 时:必填项,允许的值范围是0-23,支持的特殊符号和秒一样,含义类推
  • 日期:必填项,允许的值范围是1-31,支持的特殊符号相比秒多了?,表示与{星期}互斥,即意味着若明确指定{星期}触发,则表示{日期}无意义,以免引起冲突和混乱。
  • 月:必填项,允许的值范围是1-12(JAN-DEC),支持的特殊符号与秒一样,含义类推
  • 星期:必填项,允许值范围是1~7 (SUN-SAT),1代表星期天(一星期的第一天),以此类推,7代表星期六,支持的符号相比秒多了?,表达的含义是与{日期}互斥,即意味着若明确指定{日期}触发,则表示{星期}无意义。

比如下面这个cron表达式:

  1. // 表达的含义是:每半分钟触发一次任务
  2. 30 * * * * ?

spring提供了一个CronTrigger,通过传入一个Runnable任务和CronTrigger,就可以使用cron表达式去指定定时任务了,是不是非常方面。实际上,在工程实践上,cron表达式也是使用很多的。实际上,是执行了下面的代码:

  1. scheduler.schedule(task, new CronTrigger("30 * * * * ?"));

TaskScheduler抽象的好处是让需要执行定时任务的代码不需要指定特定的定时框架(比如Timer和Quartz)。TaskScheduler的更简单的实现是ThreadPoolTaskScheduler,它实际上代理一个jdk中的SchedulingTaskExecutor,并且也实现了TaskExecutor接口,所以需要经常执行定时任务的场景可以使用这个实现(Spring推荐)。我们再来看一下TaskExecutor和TaskScheduler的类继承关系:

通常而言,使用spring task实现定时任务有两种方式:注解和xml配置文件。这里使用xml配置文件的方式加以说明。

实战

创建Maven工程,pom.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6.  
  7. <groupId>com.rhwayfun</groupId>
  8. <artifactId>sring-task-demo</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10.  
  11. <dependencies>
  12. <dependency>
  13. <groupId>org.springframework</groupId>
  14. <artifactId>spring-context</artifactId>
  15. <version>4.2.4.RELEASE</version>
  16. </dependency>
  17. </dependencies>
  18.  
  19. <build>
  20. <plugins>
  21. <plugin>
  22. <groupId>org.apache.maven.plugins</groupId>
  23. <artifactId>maven-compiler-plugin</artifactId>
  24. <version>3.5.1</version>
  25. <configuration>
  26. <source>1.8</source>
  27. <target>1.8</target>
  28. </configuration>
  29. </plugin>
  30. </plugins>
  31. </build>
  32. </project>

示例

  1.  

开发需要执行定时任务的方法:

  1. package com.rhwayfun.task;
  2.  
  3. import org.springframework.stereotype.Component;
  4.  
  5. import java.time.LocalDateTime;
  6.  
  7. /**
  8. * @author ZhongCB
  9. * @date 2016年09月10日 14:30
  10. * @description
  11. */
  12. @Component
  13. public class App {
  14.  
  15. public void execute1(){
  16. System.out.printf("Task: %s, Current time: %s\n", 1, LocalDateTime.now());
  17. }
  18.  
  19. public void execute2(){
  20. System.out.printf("Task: %s, Current time: %s\n", 2, LocalDateTime.now());
  21. }
  22.  
  23. public void execute3(){
  24. System.out.printf("Task: %s, Current time: %s\n", 3, LocalDateTime.now());
  25. }
  26.  
  27. public void execute4(){
  28. System.out.printf("Task: %s, Current time: %s\n", 4, LocalDateTime.now());
  29. }
  30.  
  31. public void execute5(){
  32. System.out.printf("Task: %s, Current time: %s\n", 5, LocalDateTime.now());
  33. }
  34.  
  35. public void execute6(){
  36. System.out.printf("Task: %s, Current time: %s\n", 6, LocalDateTime.now());
  37. }
  38.  
  39. public void execute7(){
  40. System.out.printf("Task: %s, Current time: %s\n", 7, LocalDateTime.now());
  41. }
  42.  
  43. public void execute8(){
  44. System.out.printf("Task: %s, Current time: %s\n", 8, LocalDateTime.now());
  45. }
  46.  
  47. public void execute9(){
  48. System.out.printf("Task: %s, Current time: %s\n", 9, LocalDateTime.now());
  49. }
  50.  
  51. public void execute10(){
  52. System.out.printf("Task: %s, Current time: %s\n", 10, LocalDateTime.now());
  53. }
  54.  
  55. public void execute11(){
  56. System.out.printf("Task: %s, Current time: %s\n", 11, LocalDateTime.now());
  57. }
  58.  
  59. }

示例

spring配置文件如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:task="http://www.springframework.org/schema/task"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
  8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
  9. http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd">
  10.  
  11. <!-- 配置注解扫描 -->
  12. <context:component-scan base-package="com.rhwayfun.task"/>
  13.  
  14. <task:scheduler id="taskScheduler" pool-size="100" />
  15.  
  16. <task:scheduled-tasks scheduler="taskScheduler">
  17. <!-- 每半分钟触发任务 -->
  18. <task:scheduled ref="app" method="execute1" cron="30 * * * * ?"/>
  19. <!-- 每小时的10分30秒触发任务 -->
  20. <task:scheduled ref="app" method="execute2" cron="30 10 * * * ?"/>
  21. <!-- 每天1点10分30秒触发任务 -->
  22. <task:scheduled ref="app" method="execute3" cron="30 10 1 * * ?"/>
  23. <!-- 每月20号的1点10分30秒触发任务 -->
  24. <task:scheduled ref="app" method="execute4" cron="30 10 1 20 * ?"/>
  25. <!-- 每年10月20号的1点10分30秒触发任务 -->
  26. <task:scheduled ref="app" method="execute5" cron="30 10 1 20 10 ?"/>
  27. <!-- 每15秒、30秒、45秒时触发任务 -->
  28. <task:scheduled ref="app" method="execute6" cron="15,30,45 * * * * ?"/>
  29. <!-- 15秒到45秒每隔1秒触发任务 -->
  30. <task:scheduled ref="app" method="execute7" cron="15-45 * * * * ?"/>
  31. <!-- 每分钟的每15秒时任务任务,每隔5秒触发一次 -->
  32. <task:scheduled ref="app" method="execute8" cron="15/5 * * * * ?"/>
  33. <!-- 每分钟的15到30秒之间开始触发,每隔5秒触发一次 -->
  34. <task:scheduled ref="app" method="execute9" cron="15-30/5 * * * * ?"/>
  35. <!-- 每小时的0分0秒开始触发,每隔3分钟触发一次 -->
  36. <task:scheduled ref="app" method="execute10" cron="0 0/3 * * * ?"/>
  37. <!-- 星期一到星期五的10点15分0秒触发任务 -->
  38. <task:scheduled ref="app" method="execute11" cron="0 15 10 ? * MON-FRI"/>
  39. </task:scheduled-tasks>
  40.  
  41. </beans>

示例

编写测试代码:

  1. package com.rhwayfun.task;
  2.  
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5.  
  6. /**
  7. * @author ZhongCB
  8. * @date 2016年09月10日 14:55
  9. * @description
  10. */
  11. public class AppTest {
  12.  
  13. public static void main(String[] args) {
  14. ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/app-context-task.xml");
  15. }
  16. }

测试代码

运行测试代码,控制台会定时输出每个定时任务的日志信息,说明测试通过。

任务调度 Spring Task 4(一)的更多相关文章

  1. 任务调度 Spring Task 4(二 )

    注解和配置文件两种 第一种:配置文件方式 第一步:编写作业类 即普通的pojo,如下: import org.springframework.stereotype.Service; @Service ...

  2. Spring任务调度器之Task的使用

    Spring Task提供两种方式进行配置,正如大家所想吧,还是一种是annotation(标注),而另外一种就是XML配置了.但其实这里我觉得比较尴尬,因为任务调度这样的需求,通常改动都是比较多的, ...

  3. Spring任务调度器之Task的使用(转)

    文章转自 http://blog.csdn.net/l454822901/article/details/51829307 最近发现真的凹凸了,spring升级到3后原来已经自带任务调度器了,之前还一 ...

  4. 任务调度的方式:Timer、ScheduledExecutorService、spring task、quartz、XXL-JOB、Elastic-Job

    任务调度 定时任务调度:基于给定的时间点.给定的时间间隔.给定的执行次数自动执行的任务. Timer 介绍 Timer,简单无门槛,一般也没人用. Timer位于java.util包下,其内部包含且仅 ...

  5. 基于Spring Task的定时任务调度器实现

    在很多时候,我们会需要执行一些定时任务 ,Spring团队提供了Spring Task模块对定时任务的调度提供了支持,基于注解式的任务使用也非常方便. 只要跟需要定时执行的方法加上类似 @Schedu ...

  6. spring task 配置

    Spring对Quartz作了一个封装,同时,Spring自己也提供了一个任务定时器(spring-task),现把它总结一下.    对于Quartz,我们使用的时候主要是注重两个方面,一个是定时任 ...

  7. Quartz Spring与Spring Task总结

    Spring对Quartz作了一个封装,同时,Spring自己也提供了一个任务定时器(spring-task),现把它总结一下.    对于Quartz,我们使用的时候主要是注重两个方面,一个是定时任 ...

  8. java Quartz定时器任务与Spring task定时的几种实现,

    java Quartz定时器任务与Spring task定时的几种实现 基于java 的定时任务实现, Quartz 时间详细配置    请查阅   http://www.cnblogs.com/si ...

  9. uartz Spring与Spring Task总结

    Spring对Quartz作了一个封装,同时,Spring自己也提供了一个任务定时器(spring-task),现把它总结一下.    对于Quartz,我们使用的时候主要是注重两个方面,一个是定时任 ...

随机推荐

  1. python2函数

    1.函数的定义 函数的定义形式如下: def <name>(arg1,arg2...argN): <statements> 函数的名字必须以字母开头,可以包括下划线.函数的目的 ...

  2. HTML 块级元素与行内元素

    1.块元素一般都从新行开始,它可以容纳内联元素和其他块元素,常见块元素是段落标签'P".“form"这个块元素比较特殊,它只能用来容纳其他块元素. 2.如果没有css的作用,块元素 ...

  3. restful API(转自阮一峰)

    RESTful API 设计指南   网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). 因此,必须有一种统一的机制,方便不 ...

  4. springmvc国际化资源文件

    spring配置文件中添加 <!-- 配置国际化资源文件 --> <bean id="messageSource" class="org.springf ...

  5. 设计模式(五) 注解方式实现AOP

    1.1. Aop,  aspect object programming  面向切面编程 功能: 让关注点代码与业务代码分离! 关注点, 重复代码就叫做关注点: 切面, 关注点形成的类,就叫切面(类) ...

  6. PHP面向对象程序设计之抽象类和抽象方法

    抽象类: 抽象类不能被实例化.抽象类中只定义(或部分实现)子类需要的方法.子类可以继承它并且通过实现其中的抽象方法,使抽象类具体化. 我们可以用一个abstract关键字来定义一个抽象类,示例如下: ...

  7. python——动态类型简介

    动态类型简介 类型属于对象,而不是变量 每一个对象都有两个标准的头部信息:类型标志符和引用计数器. 对象的垃圾收集,就是通过引用计数器实现的.可以在脚本中任意使用对象而不需要考虑释放内存空间. 循环饮 ...

  8. Python-GUI编程-PyQt5

    Python-GUI编程-PyQt5 1. GUI编程是什么? GUI 全称为: Graphical User Interface;简称GUI翻译为中文为: 图形化用户接口简单理解就是:- 使用Pyt ...

  9. React Native常用组件之ListView组件

    学习iOS开发的同学应该都知道UITableView,几乎每个APP中都有它的存在,而且衍生出各种形态:那么同样,ListView就是在React Native中的tableView,而且更加简单和灵 ...

  10. jvm-内存区域与内存溢出异常

    内存区域与内存溢出异常 参考: http://www.cnblogs.com/ityouknow/p/5610232.html 所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢? ...