从实现的技术上来分类,java定时任务目前主要有三种:

  1. Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行;而且作业类需要集成java.util.TimerTask,一般用的较少。
  2. Quartz,这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行;使用起来需要继承org.springframework.scheduling.quartz.QuartzJobBean,配置稍显复杂,所以,一般会使用spring集成quartz,稍后会详细介绍;
  3. Spring3.0以后自带的task,即:spring schedule,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。

综上,spring中使用定时任务有两种方式:spring schedule和spring-quartz,接下来我们重点介绍这两种。使用前都需要引入spring的包。

<!-- spring -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${org.springframework.version}</version><type>jar</type><scope>compile</scope>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${org.springframework.version}</version><type>jar</type><scope>compile</scope>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${org.springframework.version}</version><type>jar</type><scope>compile</scope>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${org.springframework.version}</version>
</dependency>

spring schedule

1、xml配置的方式:

1)application.xml:

首先在application.xml中引入task的命名空间,以及通过task标签定义任务。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"><task:scheduler id="myScheduler"/><task:scheduled-tasks scheduler="myScheduler"><task:scheduled ref="doSomethingTask" method="doSomething" cron="0 * * * * *"/></task:scheduled-tasks>
</beans>

2)任务类:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class DoSomethingTask {public void doSomething() {System.out.println("do something");}
}

2、@schedule 注解方式:

1)application.xml

同样在application.xml中引入task的命名空间,以及启用注解驱动的定时任务。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"><task:annotation-driven/>
</beans>

2)任务类:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class DoSomethingTask {@Scheduled(cron="0 * * * * *")public void doSomething() {System.out.println("do something");}
}

3、Cron表达式:

由6~7项组成,中间用空格分开。从左到右依次是:秒、分、时、日、月、周几、年(可省略)。值可以是数字,也可以是以下符号:
*:所有值都匹配
?:无所谓,不关心,通常放在“周几”里
,:或者
/:增量值
-:区间

例如:

0 * * * * *:每分钟(当秒为0的时候)
0 0 * * * *:每小时(当秒和分都为0的时候)
*/10 * * * * *:每10秒
0 5/15 * * * *:每小时的5分、20分、35分、50分
0 0 9,13 * * *:每天的9点和13点

4、@Scheduled注解的另外两个属性:fixedRate和fixedDelay

1)fixedDelay设置的是:上一个任务结束后多久执行下一个任务;

2)fixedRate设置的是:上一个任务的开始到下一个任务开始时间的间隔;

注:如果是强调任务间隔的定时任务,建议使用fixedRate和fixedDelay,如果是强调任务在某时某分某刻执行的定时任务,建议使用cron表达式。

5、并发执行

1)spring schedule的定时任务默认是单线程的

处理方式是等待上一个任务执行完成后,再去执行下一个任务。(无论是cron还是fixedDelay、fixedRate都遵循这个原则)。下面举一些例子:

示例1:通过cron定时执行:任务运行时间6s、每5s运行一次任务

//使用注解方式创建定时任务
<task:annotation-driven/>@Component
public class testTask {private Logger logger = LoggerFactory.getLogger(testTask.class);@Scheduled(cron = "0/5 * * * * ?")public void doTask() {logger.info(Thread.currentThread().getName()+"===task run");Thread.sleep(6*1_000);logger.info(Thread.currentThread().getName()+"===task end");}
}//日志如下
2018-06-11 16:03:00.006 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:03:06.013 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end
2018-06-11 16:03:10.115 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:03:17.267 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end
2018-06-11 16:03:20.055 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:03:26.164 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end

根据日志可以看出,spring schedule默认是单线程处理的,下一个任务会等上一个运行完再执行。

示例2:换成fixedDelay

@Scheduled(fixedDelay = 5*1_000)
public void doTask() throws InterruptedException {logger.info(Thread.currentThread().getName()+"===task run");Thread.sleep(6*1_000);logger.info(Thread.currentThread().getName()+"===task end");
}
//日志如下:
2018-06-11 16:31:08.122 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:31:14.139 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end
2018-06-11 16:31:19.149 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:31:25.261 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end
2018-06-11 16:31:30.269 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:31:36.385 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end

从日志可以看出,任务结束时间再经过5s开始再次运行。

示例3:fixedRate

@Scheduled(fixedRate = 5*1_000)
public void doTask() throws InterruptedException {logger.info(Thread.currentThread().getName()+"===task run");Thread.sleep(6*1_000);logger.info(Thread.currentThread().getName()+"===task end");
}
//日志
2018-06-11 16:54:36.118 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:54:42.580 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end
2018-06-11 16:54:42.607 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:54:48.632 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end
2018-06-11 16:54:48.639 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 16:54:55.188 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end

从日志可以看出,上一个任务结束后,下一个任务立刻开始执行了,因为:fixedRate设置的上一个任务的开始时间到下一个任务开始时间的间隔。

示例4:fixedRate

上面例子,运行时间从6s改成2s,日志如下:

2018-06-11 17:08:43.086 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 17:08:45.093 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end
2018-06-11 17:08:48.025 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 17:08:50.083 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end
2018-06-11 17:08:53.239 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task run
2018-06-11 17:08:55.245 [pool-12-thread-1] INFO  service.task.testTask -pool-12-thread-1===task end

结果和我们推断的一致,两个任务的开始时间间隔是5s。

2)配置并行处理

上面的例子是同一个task,如果前一个还没跑完后面一个就不会触发,这没有太大问题。但是,假设系统中有多个task,默认spring schedule是单线程的,就会造成不同的task也不能同时运行,就不太合理了。解决方法:

方法一:配置多个线程,但这样会导致同一个task前一个还没跑完后面又被触发的问题。

<task:scheduler id="scheduler" pool-size="2" />

方法二:让任务分别运行在不同的scheduler里

<task:scheduler id="myScheduler1"/>
<task:scheduler id="myScheduler2"/>
<task:scheduled-tasks scheduler="myScheduler1"><task:scheduled ref="doSomethingTask" method="doSomething" cron="${0 * * * * *}"/>
</task:scheduled-tasks>
<task:scheduled-tasks scheduler="myScheduler2"><task:scheduled ref="doOtherThingTask" method="doOtherThing" cron="${0 * * * * *}"/>
</task:scheduled-tasks>

spring-quartz

maven中需要引入:quartz.jar、spring-context-support.jar。

示例:

1)定义任务类:(spring集成的quartz不需要集成任何类)

@Service
public class QuartzTest {public void test(){System.out.println("It's time to run :" + new Date().toString());//TODO 执行任务逻辑//........}
}

2)spring-quartz.xml配置:

a)SimpleTrigger方式:

<bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list><ref local="quartzTestTrigger" /></list></property>
</bean>
<bean id="quartzTestTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"><property name="jobDetail" ref="quartzTestJob"/><!-- 20秒后运行 --><property name="startDelay" value="20000" /><!-- 每隔三十秒重复 --><property name="repeatInterval" value="30000" />
</bean><bean id="quartzTestJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject" ref="quartzTest"></property><property name="targetMethod" value="autoRun"></property><property name="concurrent" value="false"></property><!--不并发运行-->
</bean>

b)CronTrigger方式:

<bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list><ref local="quartzTestTrigger" /></list></property><property name="startupDelay" value="500"/>
</bean>
<bean id="quartzTestTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><property name="jobDetail" ref="quartzTestJob"/><property name="cronExpression"><value>0 */1 * * * ?</value></property>
</bean><bean id="quartzTestJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject" ref="quartzTest"></property><property name="targetMethod" value="autoRun"></property><property name="concurrent" value="false"></property><!--不并发运行-->
</bean>

最后,在spring主配置文件application.xml中把上面的application-quartz.xml 包含进去即可。

spring定时任务详解spring schedule和spring-quartz相关推荐

  1. Spring学习详解(1)——Spring入门详解

    2019独角兽企业重金招聘Python工程师标准>>> 一:spring的基本用法: 1,关于spring容器: spring容器是Spring的核心,该 容器负责管理spring中 ...

  2. spring定时任务详解(@Scheduled注解)多线程讲解

    转载自 https://www.cnblogs.com/ClassNotFoundException/p/6635189.html (一)在xml里加入task的命名空间 <?xml versi ...

  3. Spring IoC详解

    Spring IoC详解 原文地址:Spring IoC详解 写在最前 本文将主要写Spring最核心的部分,为什么写这篇的原因也是因为在刚开始学习Spring的时候,学得太粗糙了.感觉学了个皮毛,从 ...

  4. Spring整合Schedule定时任务详解

    Spring整合Schedule定时任务详解 Spring 定时任务官方网站 一.概述 用Spring,就是为了简单. 但是我还是要总结下java定时任务实现的几种方式. 1.TimerTask,等于 ...

  5. Spring AOP详解(转载)所需要的包

    上一篇文章中,<Spring Aop详解(转载)>里的代码都可以运行,只是包比较多,中间缺少了几个相应的包,根据报错,几经百度搜索,终于补全了所有包. 截图如下: 在主测试类里面,有人怀疑 ...

  6. Spring JDBC详解

    <Spring JDBC详解> 本文旨在讲述Spring JDBC模块的用法.Spring JDBC模块是Spring框架的基础模块之一. 一.概述 在Spring JDBC模块中,所有的 ...

  7. Spring 体系结构详解

    Spring 体系结构详解 核心容器(Core Container) Core和Beans模块提供了Spring最基础的功能,提供IOC和依赖注入特性.这里的基础概念是BeanFactory,它提供对 ...

  8. Spring AOP详解(http://sishuok.com/forum/posts/list/281.html)

    三6.5  AspectJ切入点语法详解 6.5.1  Spring AOP支持的AspectJ切入点指示符 切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只有执行方法这一个连接 ...

  9. mysql mybatis配置_mybatis详解 与配置mybatis+spring+mysql.doc

    mybatis详解 与配置mybatis+spring+mysql.doc 还剩 30页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧, ...

最新文章

  1. 如何下载flash离线安装包
  2. SAP MM MIRO的时候,发票价格与物料主数据的价格(移动平均价)有差异的处理
  3. linux下网卡安装
  4. 电商系统设计之商品(下)
  5. 基于Rails的blog: typo
  6. 一个亿的融资在一家芯片初创公司可以烧多久?
  7. Python开发还在用virtualenv?不如了解下pipenv...#华为云·寻找黑马程序员#
  8. Matplotlib 中文用户指南 3.5 密致布局指南
  9. 征信报告上那些你不知道的事
  10. windows 勾子简介
  11. [Linux] 使用 SCP 指令,讓您傳送檔案至遠端、下載檔案
  12. 易筋SpringBoot 2.1 | 第七篇:JPA访问MySQL
  13. 一步步教你破解WIFI无线WEP网络密钥
  14. 4个很 丝滑 的 Veu 路由过渡动效
  15. 基于php+mysql的学员量化考评系统
  16. usb Android gentoo,gentoo usb 鼠标
  17. 本地电脑连接windows云服务器
  18. 时间复杂度 O(1),O(n),O(n^2),O(logn),O(nlogn) 详解
  19. 看板 工具_2019年14种最佳看板工具
  20. PMP分享|不在挣扎中蜕变,就在安逸中消亡

热门文章

  1. 41. Pandas读取Excel绘制直方图
  2. Linux下的菜刀weevely
  3. 我电脑中乱七八糟的TXT文件
  4. 微信公众平台开发入门--PHP,实现自动回复文本,图文,点击事件
  5. 素颜聚合登录多渠道便捷登录平台接入【免费社会化登录计划】
  6. Android开发者心酸史
  7. Java 线程池原理和队列详解
  8. Python入门(第二节):Python编译器安装
  9. php通过$_SERVER获取当前页面完整URL地址
  10. Macbook pro 总是自动关机