任务调度是大多数应用系统的常见需求之一,拿论坛来说:每个半个小时生成精华文章的RSS文件,每天凌晨统计论坛用户的积分排名,每隔30分钟执行对锁定过期的用户进行解锁。以上都是以时间为关注点的调度,事实上我们在实际中还会使用资源上的调度,如线程的使用。spring提供了Quartz,Timer,Executor的支持,使得使用时更加简化。

一、Quartz

1.Quartz提供了强大的任务调度机制,提出了调度器、任务、触发器这三个核心概念。

Job: 是一个接口,只有一个执行方法,开发者想要完成什么任务,可以自己实现。

JobDetail: 描述Job实现类及其他静态信息,Quartz每次执行job时,都是创建一个job实例。

Trigger: 其来触发Job执行的时间触发规则,主要有SimpleTrigger和CronTrigger两个子类。

Scheduler: Quartz运行的一个独立容器。Trigger和JobDetail可以注册进来,其允许外部通过接口方法来访问它们。 通过SchedulerFactory创建一个Scheduler实例,其拥有一个SchedulerContext,保存上下文信息。

任务的信息保存在JobDataMap实例中,Job有个StatefulJob子接口,对于该有状态的任务,任务对JobDataMap的更改会保存下来影响后续的执行,因此不能并发执行。而无状态的job可以并发执行。如图所示:

默认情况下,Quartz的运行信息是保存在内存中的,因为内存中的数据访问最快。如果需要持久化任务调度信息,Quartz允许用户通过调整其属性文件,将信息保存到数据库中。

2.spring中的Quartz

spring为创建Quartz中的Scheduler、Trigger和JobDetail提供了变量的FactoryBean类,首先看实例配置:

<bean id="myService" class="org.slob.service.MyService"></bean>

    <bean id="quartzTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject">
            <ref bean="myService" />
        </property>
        <property name="targetMethod">
            <value>quartzJob</value>
        </property>
    </bean>     <bean id="quartzTaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail">
            <ref bean="quartzTask" />
        </property>
        <property name="cronExpression">
            <value>${cron.expression}</value>
        </property>
    </bean>     <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="quartzTaskTrigger" />
            </list>
        </property>
    </bean>
    

在实例中我们周期执行的是myService中的quartzJob方法,执行的周期由${cron.expression}来指定。在此trigger为CronTriggerBean,然后开启调度器startQuartz。

下面介绍cron expression的格式:

一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素,从左到右为:

0-59     0-59        0-23    1-31     1-12(*)     1-7(*)   1970-2099

每个元素都显示规定一个值,一个区间 " - " ,一个列表或通配符;一个问号表示不想设置该字段(在星期和日期中使用),“/"字符用于指定增量,如如:“0/15”在秒域意思是每分钟的0,15,30和45秒。其中"L" 在月字段表示该月的最后一天,在周字段表示SAT或7,;"W"只会在日期中出现表示工作日;"#" 只会在星期字段中出现,用于指定本月的某某天,如“6#3”表示本月第三周的星期五(6表示星期五,3表示第三周);"C "在日期和星期字段中出现,这个表达式的值依赖于相关的“日历”的计算结果,如果没有“日历”关联,则等价于所有包含的“日历”。如:日期域是“5C”表示关联“日历”中第一天,或者这个月开始的第一天的后5天。星期域是“1C”表示关联“日历”中第一天,或者星期的第一天的后1天,也就是周日的后一天(周一)。

如表达式:

“10 */1 * * * ?”意为:从10秒开始,每1分钟执行一次

"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发

"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发

"0 15 10 L * ?" 每月最后一日的上午10:15触发

"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发

"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发

二、Java Timer

1.Java通过java.util.Timer和java.util.TimerTask这两个类提供了简单的任务调度功能,允许按照固定频率重复执行某项任务,其只适合对执行时间非常短的任务进行调度,因为TimerTask都在同一背景线程中执行,长时间的任务会严重影响Timer的调度工作。因为如果一个TimerTask的执行占用了过多的时间,后面的任务就会受到影响,在调度时间轴上受到了“挤压”,可能会造成“扎堆”执行的情况。

TimerTask实现了Runnable接口, 我们自己在run()方法中定义任务逻辑,Timer负责制定规则并调度TimerTask。

2.spring中的Timer

spring提供了JDK Timer支持,更加方便使用timer,实力配置如下:

<bean id="myService" class="org.slob.service.MyService"/>

    <bean id="timerTask" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
        <property name="targetObject">
            <ref bean="myService"/>
        </property>
        <property name="targetMethod">
            <value>timerJob</value>
        </property>
    </bean>
    <bean id="scheduleTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">   
        <property name="timerTask" ref="timerTask" />   
        <property name="delay">
            <value>300000</value>
        </property>
        <property name="period">   
            <value>86400000</value>   
        </property>   
    </bean>  
    <bean class="org.springframework.scheduling.timer.TimerFactoryBean">   
        <property name="scheduledTimerTasks">   
               <list>
                   <ref bean="scheduleTask"/>
               </list>   
        </property>  
    </bean>

该配置在延迟5分钟后,每个24小时执行一次myService中的timerJob方法,如果更加细致的调度,则timer显得力不从心!

三、Jdk Executor

1. JDK5.0中的java.util.concurrent包,提供了功能强大、更高层次的线程构造器。执行器Executor是并发工具包中的一个重要的类,它对Runnable实例的执行进行了抽象,实现者可以提供具体的实现:如简单的以一个线程来运行Runnable,或者通过一个线程池为Runnable提供共享线程。其将“任务提交”和“任务执行”两者分离解耦。

Executor只有一个方法:void execute(Runnable command),接收实现了Runnable的实例,代表了一个待执行的任务。Executor接口还有两个子接口:ExecutorService和SchedulerExecutorService,前者添加了结束任务的管理方法,后者可以对任务进行调度。

JDK ThreadPoolExecutor类实现了Executor和ExecutorService接口,其使用线程池对任务进行调度。 创建线程的开销较大,因此最好能重用同一个线程,动态创建线程池中的线程,防止资源消耗引发的系统性能问题。ThreadPoolExecutor的子类ScheduledThreadPoolExecutor实现ScheduledExecutorService接口,添加了对人物的调度功能。

java.util.concurrent中提供了一个综合性的工厂类Executors,它拥有很多静态工厂方法:

public static ExecutorService newFixedThreadPool(int nThreads):创建一个线程池,重复使用一个固定的线程运行一个共享的无界队列。

public static ExecutorService  newCachedThreadPool():线程池是动态的,不够用时创建新的线程,长时间不用的线程将被回收。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize,ThreadFactory threadFactory):创建一个线程池,可在指定延迟后运行或者定期地执行。

2.spring与executor

spring的发现包中预定义了一些TaskExecutor实现。org.springframework.core.task.TaskExecutor接口的实现类很多,且有一个子接口SchedulingTaskExecutor。

SyncTaskExecutor:该实现不会异步执行任务,每次调用都在发起调用的主线程中。

下面是SchedulingTaskExecutor的实现类:

SimpleAsynTaskExecutor:这个实现没有实现使用线程池,在每次执行任务时都创建一个新线程,支持对并发总数设限

ConcurrentTaskExecutor:该类是JDK Executor的适配器,以便将JDK Executor当成spring的TaskExecutor使用

SimpleThreadPoolTaskExecutor:其是SimpleThreadPool的子类,监听spring的生命周期回调,当用户有线程池,需要Quartz和非Quartz组件中共用时,其发挥作用。

ThreadPoolTaskExecutor:其只可在JDK 5.0中使用,方便spring中配置一个ThreadPoolExecutor,并把它包装成TaskExecutor

TimerTaskExecutor:该类使用一个Timer作为其后台的实现。

Spring任务调度的更多相关文章

  1. spring 任务调度quartz

    简单记录一下spring任务调度quartz的例子 首先添加包 quartz-2.2.3.jar 然后写个简单的TestJob类 package com.job; import java.util.D ...

  2. Spring任务调度之Quartz

    一.Quartz作业类的继承方式来讲,可以分为两类: 作业类需要继承自特定的作业类基类,如Quartz中需要继承自org.springframework.scheduling.quartz.Quart ...

  3. Spring任务调度之Timer

    一.分类 由于现在大部分的系统都是采用了spring,所以所有的例子都结合spring来构建,目前主要的任务调度分为三种: Java自带的java.util.Timer类,这个类允许你调度一个java ...

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

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

  5. Spring(十)Spring任务调度

    一.计划任务 需要定时执行一些计划(定时更新等),这样的计划称之为计划任务 Spring抽象封装了Java提供的Timer与TimerTask类 也可以使用拥有更多任务计划功能的Quartz 二.Ti ...

  6. Spring任务调度之Quartz集成

    推荐一个博客:http://blog.csdn.net/column/details/14251.html 基本概念 Job:是一个接口,只有一个方法void execute(JobExecution ...

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

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

  8. Spring任务调度实战之Quartz Simple Trigger(转)

     启动时执行和定时执行: 本文地址:http://blog.csdn.net/kongxx/article/details/6751300 在spring中对任务调度的集成除了使用JDK自带的Time ...

  9. Spring任务调度<task:scheduled-tasks>【含cron参数详解】 (转载)

    Spring内部有一个task是Spring自带的一个设定时间自动任务调度 task使用的时候很方便,但是他能做的东西不如quartz那么的多! 可以使用注解和配置两种方式,配置的方式如下 引入Spr ...

随机推荐

  1. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.5.4

    If $\dim \scrH=3$, then $\dim \otimes^3\scrH =27$, $\dim \wedge^3\scrH =1$ and $\dim \vee^3\scrH =10 ...

  2. POJ 3107-Godfather(树形dp)

    题意: 有n个节点的树,删除一个点,得到的最大联通分支最小,求这样点的集合 分析: dp[i]表示删除i所得最大联通分支,遍历一遍节点即可,该题用vector会超时 #include <map& ...

  3. Tourism Planning(HDU 4049状压dp)

    题意:n个朋友去游览m个城市,给出每个人对每个城市的兴趣值,和每人去每个城市的花费,如果两人在一个城市有一个价值,若多于2人这这个价值是任意两人产生价值的总和.在去每个城市的过程中人可以随便离开,也可 ...

  4. visual studio 中使用git

    原文链接:http://my.oschina.net/gal/blog/141442 osc终于全面开放git库了,这是我一直期待的事,也是促使我从CSDN转回OSC社区的重要原因之一.而这次我来教大 ...

  5. gpg: no valid OpenPGP data found

    gpg: no valid OpenPGP data found

  6. Django model中 双向关联问题,求帮助

    Django model中 双向关联问题,求帮助 - 开源中国社区 Django model中 双向关联问题,求帮助

  7. 5个经典的JavaScript面试基础问题

    JavaScript程序员在IT领域中的需求量非常巨大.如果你非常精通JavaScript,你会有很多换工作.涨薪水的机会.但是在一家公司录用你之前,你必须顺利通过面试,证明你的技能.在本文中,我将向 ...

  8. 优步(UBER)发布2016年春节出境游出行报告

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  9. 电脑突然死机,系统日志记录事件ID=6008

    刚才正在写代码,在一次保存之后,正要刷新看下效果,电脑突然关机,没有任何提示或延迟.我的笔记本电池是一直插上的,也连接着电源. 重新开机之后,找到系统日志查看.只有这一条错误记录:非正常关机,事件60 ...

  10. 问题-Delphi控件选择卡自动选择与滚动方法

    问题现象: 在D7的控件工具条中每次要手动点向左向右很累,有没有方法可以自动移动.   问题解决: REGEDIT4 [HKEY_CURRENT_USER\Software\Borland\Delph ...