Spring任务调度
任务调度是大多数应用系统的常见需求之一,拿论坛来说:每个半个小时生成精华文章的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任务调度的更多相关文章
- spring 任务调度quartz
简单记录一下spring任务调度quartz的例子 首先添加包 quartz-2.2.3.jar 然后写个简单的TestJob类 package com.job; import java.util.D ...
- Spring任务调度之Quartz
一.Quartz作业类的继承方式来讲,可以分为两类: 作业类需要继承自特定的作业类基类,如Quartz中需要继承自org.springframework.scheduling.quartz.Quart ...
- Spring任务调度之Timer
一.分类 由于现在大部分的系统都是采用了spring,所以所有的例子都结合spring来构建,目前主要的任务调度分为三种: Java自带的java.util.Timer类,这个类允许你调度一个java ...
- Spring任务调度器之Task的使用
Spring Task提供两种方式进行配置,正如大家所想吧,还是一种是annotation(标注),而另外一种就是XML配置了.但其实这里我觉得比较尴尬,因为任务调度这样的需求,通常改动都是比较多的, ...
- Spring(十)Spring任务调度
一.计划任务 需要定时执行一些计划(定时更新等),这样的计划称之为计划任务 Spring抽象封装了Java提供的Timer与TimerTask类 也可以使用拥有更多任务计划功能的Quartz 二.Ti ...
- Spring任务调度之Quartz集成
推荐一个博客:http://blog.csdn.net/column/details/14251.html 基本概念 Job:是一个接口,只有一个方法void execute(JobExecution ...
- Spring任务调度器之Task的使用(转)
文章转自 http://blog.csdn.net/l454822901/article/details/51829307 最近发现真的凹凸了,spring升级到3后原来已经自带任务调度器了,之前还一 ...
- Spring任务调度实战之Quartz Simple Trigger(转)
启动时执行和定时执行: 本文地址:http://blog.csdn.net/kongxx/article/details/6751300 在spring中对任务调度的集成除了使用JDK自带的Time ...
- Spring任务调度<task:scheduled-tasks>【含cron参数详解】 (转载)
Spring内部有一个task是Spring自带的一个设定时间自动任务调度 task使用的时候很方便,但是他能做的东西不如quartz那么的多! 可以使用注解和配置两种方式,配置的方式如下 引入Spr ...
随机推荐
- ramdisk作为根文件系统的配置
ramdisk作为根文件系统的配置 http://wenku.baidu.com/link?url=oKj45hKtIANfoVzmoFAmWEvESHiqgWysxPASelpzaXk35gWb1I ...
- 上传文件出错:org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly
最近做一个web项目中有上传文件的功能,已经写出并在本地和部署到服务器上测试了好几个文件上传都没问题(我用的是tomcat).后来又上传了一个700多K的文件(前边的都是不足600K的,并且这个wor ...
- 清理vs工程文件(python2.7)
本文记录了两种方法,用于对vs目录的清理工作,这两种方法都是用python2.7实现的,一个是基于文件的扩展名,一个是基于文件的大小: 基于文件大小的清理脚本: #-*- coding:utf-8 - ...
- class0513(html基础加强2)
使用VS创建网页 新建Web项目(新建→ASP.Net Web应用程序),新建html页面(添加→新建项→Web→HTML页) 查看页面的方式: 切换到“设计”视图,可以在这里查看初步的预览效果,不是 ...
- 2014年25 款最新最棒的jQuery插件
网络上提供了大量非常有用的 jQuery 插件,帮助大家完善网站的体验.所以我们在这里收集了 2014 年发布的,并且是非常有用的插件,希望能帮助大家找到自己需要并且喜欢的,提升网站的质量! HAMM ...
- Thinking in Java
今天无意中看到了这本书(Thinking in Java)的中关于多态的一段描述,瞬间就感觉到了多态原来是这样的.
- sqlserver 出现 因为文件组 'PRIMARY' 已满 的解决办法 有可能是磁盘剩余空间不足 导致的
一般虚拟主机提供商是通过限制数据库文件的大小来实现提供定制的数据库空间的.当你把从虚拟数据库空间备份下来的文件恢复到自己的服务器上时,这个限制还是存在的.找到数据库文件 给增加个数据文件就好了 解决办 ...
- MariaDB-5.5.32源码编译安装
MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可.开发这个分支的原因之一是:Oracle公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区采用分 ...
- Spark的部署方式
1.Spark的应用程序部署 2.Spark的集群部署
- 第3组UI组件:AdapterView及其子类
1 AdapterView类简介 1.1 AdapterView组件是一组重要的组件,AdapterView本身是一个抽线类,实际使用更多的都是Adapter相关子类,AdapterView具有如下特 ...