定时任务知多少(一)——Spring实现内存级quartz
2015-09-30 23:08
309 查看
开发需求中,我们经常会遇到定时处理的需求,比如说定时提醒用户还款、定时备份数据库、定时去合作公司文件服务器读取数据、产品自动下架、用户所下的订单超时取消……等等等等,从本篇文章开始,我们来一起讨论一下项目中定时任务的应用。
然而我们都知道:是先有业务,再有技术。技术是为业务而生的。所以对于不同的需求,我们需要使用不同的技术,来合理的解决需求的问题。总结一下,通过以下四个技术层面,能够解决几乎所有的定时需求:
1、Spring实现的内存级quartz;
2、JDK中Timer及JDK中其他定时处理类;
3、集成Spring,将quartz持久化到mongodb中;
4、quartz集群。
……
今天,我们来讲第一个,也是最简单的一个。
定时任务将执行的方法类如下:
这样就可以了,上面的配置加方法,就可以执行定时任务了,很简单吧。
下面我们来大概说一下它的原理。
上面的这种定时任务的实现,还是非常普遍的,因为使用起来非常的简单,只需要一个Spring的简单的配置,即可完成需求。实际上,这是Spring做的一个对Quartz的一个比较完整的实现,所以我们用来起来才没有感觉到Quartz的存在,所以才会觉得很简单。
我们通过上面Spring的配置,通过设置cronExpression,我们可以使要执行的方法周期性的执行。比如每天晚上12点钟,准时备份数据库,比如还差3天用户将逾期时,发送提醒短信等等。我们都可以使用该种方式执行。
尺有所长,寸有所短。尽管上述方法用起来很方便,但是我能够容纳它的缺点,才能够对症下药。
缺点如下:
1、该种方法,是将定时任务序列化到内存当中的。也就是说,当系统重新部署,需要重启服务器时,该定时任务会从内存中清除(几乎是废话,应用服务器都停了,定时任务还怎么能够在内存当中。。),当应用服务器重新启动后,定时任务才会重新载入内存当中。
所以说,这种定时任务,应用服务器停止时间如果比较长的话,则当日此期间未执行的定时任务,就没有机会执行了。
2、执行执行并不是非常准确的(即执行时间不准确)。也就是说定点儿执行的定时任务,到了时间可能仍然没有执行。这是为什么呢?定时任务,说白了,就是一个进程。应用服务器启动时,定时任务进入内存,并进入阻塞状态。这时,我们可以理解为有一个timer不断去扫面执行时间。当到执行时间是,经过内存调度,即将执行的定时任务进入就绪状态,等待CPU进行调度,注意它并不会阻塞其他线程的调度,而是将自己置于就绪状态等待CPU空闲时调度。所以说,如果CPU一直忙碌的话,就会发生定时任务到时间仍未执行的情况。
综合上述这两种缺点,我们就清楚了如何、以及合适使用该种定时任务了。
实际应用中,由于这种定时任务的需求比较特殊,我们经常会将定时任务分离出来,将其作为一个独立的项目,独立部署。因为应用服务器是需要更改的,不断的产品迭代、产品的上线,很可能会重新启动应用服务器,为了不对定时任务造成影响,我们通常会将其分离出来对部署。
由于定时任务,并非准确执行,我们需要容忍它这一点(其实相差时间不会很大)。
本文只是简单介绍了定时任务,非常简单的一种实现,接下来我将会介绍quartz强大的功能,敬请期待。
然而我们都知道:是先有业务,再有技术。技术是为业务而生的。所以对于不同的需求,我们需要使用不同的技术,来合理的解决需求的问题。总结一下,通过以下四个技术层面,能够解决几乎所有的定时需求:
1、Spring实现的内存级quartz;
2、JDK中Timer及JDK中其他定时处理类;
3、集成Spring,将quartz持久化到mongodb中;
4、quartz集群。
……
今天,我们来讲第一个,也是最简单的一个。
一、Spring实现的内存级quartz
该定时任务,主要是Spring对quartz框架做的一个实现。它只需要进行简单的配置,即可实现定时任务。配置如下:<?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:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd" default-lazy-init="true"> <!--注入一个bean --> <bean id="testQtz" class="com.quartz.TestQtz" /> <!--指定定时执行的方法 --> <bean id="testQtzJobMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <ref bean="testQtz" /> </property> <property name="targetMethod"> <value>executeQtz</value> <!--指定testQtz Bean中,定时执行的方法名称 --> </property> </bean> <!-- ======================== 调度触发器 ======================== --> <!-- 设置几点开始周期性 的 执行 --> <bean id="testQtzCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="testQtzJobMethod" /> <property name="cronExpression" value="0 01 0 * * ?" /> <!-- 工作日的 00:01分执行 --> </bean> <!-- ======================== 调度工厂 ======================== --> <!-- 调度工厂 --> <bean id="SpringJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref local="testQtzCronTrigger" /> </list> </property> </bean> </beans>
定时任务将执行的方法类如下:
package com.quartz.testQtz; public class TestQtz { private static int counter = 0; public void executeQtz() { counter++; System.out.println("第 " + counter +" 次执行"); } }
这样就可以了,上面的配置加方法,就可以执行定时任务了,很简单吧。
下面我们来大概说一下它的原理。
上面的这种定时任务的实现,还是非常普遍的,因为使用起来非常的简单,只需要一个Spring的简单的配置,即可完成需求。实际上,这是Spring做的一个对Quartz的一个比较完整的实现,所以我们用来起来才没有感觉到Quartz的存在,所以才会觉得很简单。
我们通过上面Spring的配置,通过设置cronExpression,我们可以使要执行的方法周期性的执行。比如每天晚上12点钟,准时备份数据库,比如还差3天用户将逾期时,发送提醒短信等等。我们都可以使用该种方式执行。
尺有所长,寸有所短。尽管上述方法用起来很方便,但是我能够容纳它的缺点,才能够对症下药。
缺点如下:
1、该种方法,是将定时任务序列化到内存当中的。也就是说,当系统重新部署,需要重启服务器时,该定时任务会从内存中清除(几乎是废话,应用服务器都停了,定时任务还怎么能够在内存当中。。),当应用服务器重新启动后,定时任务才会重新载入内存当中。
所以说,这种定时任务,应用服务器停止时间如果比较长的话,则当日此期间未执行的定时任务,就没有机会执行了。
2、执行执行并不是非常准确的(即执行时间不准确)。也就是说定点儿执行的定时任务,到了时间可能仍然没有执行。这是为什么呢?定时任务,说白了,就是一个进程。应用服务器启动时,定时任务进入内存,并进入阻塞状态。这时,我们可以理解为有一个timer不断去扫面执行时间。当到执行时间是,经过内存调度,即将执行的定时任务进入就绪状态,等待CPU进行调度,注意它并不会阻塞其他线程的调度,而是将自己置于就绪状态等待CPU空闲时调度。所以说,如果CPU一直忙碌的话,就会发生定时任务到时间仍未执行的情况。
综合上述这两种缺点,我们就清楚了如何、以及合适使用该种定时任务了。
实际应用中,由于这种定时任务的需求比较特殊,我们经常会将定时任务分离出来,将其作为一个独立的项目,独立部署。因为应用服务器是需要更改的,不断的产品迭代、产品的上线,很可能会重新启动应用服务器,为了不对定时任务造成影响,我们通常会将其分离出来对部署。
由于定时任务,并非准确执行,我们需要容忍它这一点(其实相差时间不会很大)。
本文只是简单介绍了定时任务,非常简单的一种实现,接下来我将会介绍quartz强大的功能,敬请期待。
相关文章推荐
- Java基础(七)深入解读泛型(2)
- Java基础(六)深入解读泛型(1)
- 如何实现XA式、非XA式Spring分布式事务
- JAVA 生成随机数
- JAVA 并发编程学习(1)之基本概念
- Ajax是啥
- JavaSE实战——反射技术
- JAVA 实例 判断偶数和判断瑞年
- java重写与重载的区别
- eclipse中使用真机(已root)测试android程序时,看不到程序包data文件夹下的数据
- JAVA 运算符和条件结构
- 【Java EE 学习 51】【Spring学习第三天】【cglib动态代理】【AOP和动态代理】【切入点表达式】
- WebService(三)—JDK内置JAX-RS实现Rest WebService
- java中scanner的使用(二)
- 多线程系列三——java线程间通信
- 【Java笔记一】Filter过滤器
- java中Scanner 的使用(一)
- WebService(二)—JDK内置JAX-WS实现SOAP WebService
- 谈谈对Spring IOC的理解
- SSH搭建web java