说明:这几天同事在项目中增加了几个定时任务,今天闲下来,自己也去看了看,随便在网上查找了一些相关资料,留个脚印,以备不时之需。
Spring提供的三种定时任务机制及其比较:
来源:http://blog.csdn.net/52rainbow/article/details/4004206
1. 基于Quartz的定时机制:
下面详细解释这个类图中涉及的关键类及其使用场景
1.1. SchedulerFactoryBean:
这是Spring中基于Quartz的定时机制入口,只要Spring容器装载了这个类,Quartz定时机制就会启动,并加载定义在这个类中的所有trigger.
Spring配置范例:
<bean id="sfb" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- 添加触发器 --> <property name="triggers"> <list> <ref local="appSubscTrigger" /> </list> </property> <!-- 添加listener --> <property name="globalTriggerListeners"> <list> <ref local="myTaskTriggerListener" /> </list> </property> </bean>
1.2. CronTriggerBean:
实现了Trigger接口,基于Cron表达式的触发器,这种触发器的好处是表达式与linux下的crontab一致,能够满足非常复杂的定时需求,也容易配置。
Spring配置范例:
<bean id="notifyTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="notifyJobDetail" /> <property name="cronExpression" value="${notify_trigger_cron_expression}" /> </bean>
1.3. SimpleTriggerBean:
该类也实现了Trigger接口,基于配置的定时调度 ,这个触发器的优点在于很容易配置一个简单的定时调度策略。
Spring配置范例:
<bean id="simpleReportTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail"> <ref bean="reportJob"/> </property> <property name="startDelay"> <value>3600000</value> </property> <property name="repeatInterval"> <value>86400000</value> </property> </bean>
1.4. JobDetailBean:
JobDetail类的简单扩展,能够包装一个继承自QuartzJobBean的普通Bean,使之成为定时运行的Job。
缺点是包装的Bean必须继承自一个指定的类,通用性不强,对普通Job的侵入性过强,不推荐使用。
1.5. MethodInvokingJobDetailFactoryBean:
Spring提供的一个不错的JobDetail包装工具,能够包装任何bean,并执行类中指定的任何stati或非static的方法,避免强制要求bean去实现某接口或继承某基础类。
Spring配置范例:
<bean id="notifyJobDetail" parent="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="notifyServerHandler" /> <property name="targetMethod" value="execute" /> </bean>
1.6. 关于TriggerListener和JobListener:
Quartz中提供了类似WebWork的拦截器的功能,系统执行任务前或任务执行完毕后,都会检查是否有对应的Listener需要被执行,这种AOP的思想为我们带来了灵活的业务需求实现方式。
例如现在有一个简单的业务要求:任务执行前先判断当前服务器是否为task服务器,不是则不执行任务。对于这种业务需求,我们可以简单的实现一个TriggerListener,并将其插入SchedulerFactoryBean的globalTriggerListeners中,这样所有的job在执行前后都会调用TriggerListener中对应的方法。
代码范例:
public class MyTaskTriggerListener implements TriggerListener { protected static final Log logger = LogFactory.getLog(MyTaskTriggerListener.class); /** * 需要运行task任务的机器列表 */ private String taskServers; public String getName() { return "MyTaskTriggerListener"; } public void triggerComplete(Trigger arg0, JobExecutionContext arg1, int arg2) { } public void triggerFired(Trigger arg0, JobExecutionContext arg1) { } public void triggerMisfired(Trigger arg0) { } /** * 判断当前服务器是否为task服务器,来决定是否执行task * @return */ public boolean vetoJobExecution(Trigger arg0, JobExecutionContext arg1) { String serverName; try { serverName = InetAddress.getLocalHost().getHostName();//获取主机名 } catch (UnknownHostException e) { e.printStackTrace(); return true; } if (taskServers.indexOf(serverName) > -1) { if (logger.isInfoEnabled()) { logger.info("this is a task server, job will be executed"); } return false; } else { if (logger.isInfoEnabled()) { logger.info("this is not a task server, job will be vetoed"); } return true; } } public String getTaskServers() { return taskServers; } public void setTaskServers(String taskServers) { this.taskServers = taskServers; } }
2. 基于Timer的定时机制:
JDK提供了基础的定时类:Timer,在这个类的基础上,Spring提供了一套简单的定时机制。
下面详细解释这个类图中涉及的关键类及其使用场景:
2.1. TimerFactoryBean:
这个类非常类似Quartz中的SchedulerFactoryBean,是基于Timer的定时机制的入口,Spring容器装载此类后会自动开始定时器。
Spring配置范例:
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean"> <property name="scheduledTimerTasks"> <list> <ref bean="scheduledTask" /> </list> </property> </bean>
2.2. ScheduledTimerTask:
类似于Quartz中的Trigger的SimpleTriggerBean实现,任务是在设定的时间触发并执行配置的任务,特点是配置简单、明了,使用于简单的任务触发逻辑。
Spring配置范例:
<bean id=”scheduledReportTask” class=”org.springframework.scheduling.timer.ScheduledTimerTask”> <property name=”timerTask”> <ref bean =”reportTimerTask”/> </property> <property name=”period”> <value>86400000</value> </property> </bean>
2.3. TimerTask抽象类:
普通task实现必须要继承的父类,主要包含一个run()的方法,类似Quartz中的QuartzJobBean,对应用侵入性较强,也不推荐使用。
2.4. MethodInvokingTimerTaskFactoryBean:
类似Quartz中的MethodInvokingJobDetailFactoryBean,用于封装任何bean,并可以执行bean中的任意方法,不再复述。
3. 基于Executor的定时机制:
这种定时机制与上面两种定时机制没有太大区别,特别是在配置和实现功能上,不同的是它的核心是基于ScheduledExecutorService(ScheduledThreadPoolExecutor是默认实现),一种JDK5.0中提供的基于线程的并发机制,关于JDK5中的线程池的概念及其一些深入分析,请参考老唐的博客:http://blog.csdn.net/sfdev/archive/2008/12/30/3648457.aspx 这里不再复述。
4. 三种定时机制的比较和案例分析:
看完了这三种定时机制,各有各的优劣,不同场景下我们应该灵活选择不同的定时机制。总的来说,如果我们需要简单的定时器,我们可以选用基于timer的定时器,如果定时规则较为复杂,我们可以选用基于Quartz的定时器,如果我们要用到线程池来处理异步任务,我们可以选用基于Executor的定时机制,虽然只是任务实现中用到线程池,毕竟也是一脉相承的,当然也可以用Quartz的定时器+基于Executor的任务线程池,完全没有任何冲突的。
spring定时任务时间格式cronExpression设置:
org.springframework.scheduling.quartz.CronTriggerBean允许你更精确地控制任务的运行时间,只需要设置其cronExpression属性。
一个cronExpression表达式有至少6个(也可能是7个)由空格分隔的时间元素。从左至右,这些元素的定义如下:
1.秒(0–59)
2.分钟(0–59)
3.小时(0–23)
4.月份中的日期(1–31)
5.月份(1–12或JAN–DEC)
6.星期中的日期(1–7或SUN–SAT)
7.年份(1970–2099)
示例:
0 0 10,14,16 * * ? ----每天上午10点,下午2点和下午4点
0 0,15,30,45 * 1-10 * ? ----每月前10天每隔15分钟
30 0 0 1 1 ? 2012 ----在2012年1月1日午夜过30秒时
0 0 8-5 ? * MON-FRI ----每个工作日的工作时间
各个时间可用值如下:
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日 1-31 , - * ? / L W C
月 1-12 or JAN-DEC , - * /
周几 1-7 or SUN-SAT , - * ? / L C #
年 (可选字段) empty, 1970-2099 , - * /
可用值详细分析如下:
“*”----字符可以用于所有字段,在“分”字段中设为"*"表示"每一分钟"的含义。
“?”----字符可以用在“日”和“周几”字段. 它用来指定 '不明确的值'. 这在你需要指定这两个字段中的某一个值而不是另外一个的时候会被用到。在后面的例子中可以看到其含义。
“-”----字符被用来指定一个值的范围,比如在“小时”字段中设为"10-12"表示"10点到12点"。
“,”----字符指定数个值。比如在“周几”字段中设为"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday"。
“/”----字符用来指定一个值的的增加幅度. 比如在“秒”字段中设置为"0/15"表示"第0, 15, 30, 和 45秒"。而 "5/15"则表示"第5, 20, 35, 和 50". 在'/'前加"*"字符相当于指定从0秒开始. 每个字段都有一系列可以开始或结束的数值。对于“秒”和“分”字段来说,其数值范围为0到59,对于“小时”字段来说其为0到23, 对于“日”字段来说为0到31, 而对于“月”字段来说为1到12。"/"字段仅仅只是帮助你在允许的数值范围内从开始"第n"的值。
“L”----字符可用在“日”和“周几”这两个字段。它是"last"的缩写, 但是在这两个字段中有不同的含义。例如,“日”字段中的"L"表示"一个月中的最后一天"。对于一月就是31号对于二月来说就是28号(非闰年)。而在“周几”字段中, 它简单的表示"7" or "SAT",但是如果在“周几”字段中使用时跟在某个数字之后, 它表示"该月最后一个星期×"。比如"6L"表示"该月最后一个周五"。当使用'L'选项时,指定确定的列表或者范围非常重要,否则你会被结果搞糊涂的。
“W”----可用于“日”字段。用来指定历给定日期最近的工作日(周一到周五) 。比如你将“日”字段设为"15W",意为: "离该月15号最近的工作日"。因此如果15号为周六,触发器会在14号即周五调用。如果15号为周日, 触发器会在16号也就是周一触发。如果15号为周二,那么当天就会触发。然而如果你将“日”字段设为"1W", 而一号又是周六, 触发器会于下周一也就是当月的3号触发,因为它不会越过当月的值的范围边界。'W'字符只能用于“日”字段的值为单独的一天而不是一系列值的时候。“L”和“W”可以组合用于“日”字段表示为'LW',意为"该月最后一个工作日"。
“#”----字符可用于“周几”字段。该字符表示“该月第几个周×”,比如"6#3"表示该月第三个周五( 6表示周五而"#3"该月第三个)。再比如: "2#1" = 表示该月第一个周一而 "4#5" = 该月第五个周三。注意如果你指定"#5"该月没有第五个“周×”,该月是不会触发的。
“C”----字符可用于“日”和“周几”字段,它是"calendar"的缩写。 它表示为基于相关的日历所计算出的值(如果有的话)。如果没有关联的日历, 那它等同于包含全部日历。“日”字段值为"5C"表示"日历中的第一天或者5号以后",“周几”字段值为"1C"则表示"日历中的第一天或者周日以后"。
注:对于“月份”字段和“周几”字段来说合法的字符都不是大小写敏感的。
一些例子:
"0 0 12 * * ?" ----每天中午十二点触发
"0 15 10 ? * *" ----每天早上10:15触发
"0 15 10 * * ?" ----每天早上10:15触发
"0 15 10 * * ? *" ----每天早上10:15触发
"0 15 10 * * ? 2005" ----2005年的每天早上10:15触发
"0 * 14 * * ?" ----每天从下午2点开始到2点59分每分钟一次触发
"0 0/5 14 * * ?" ----每天从下午2点开始到2:55分结束每5分钟一次触发
"0 0/5 14,18 * * ?" ----每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发
"0 0-5 14 * * ?" ----每天14:00至14:05每分钟一次触发
"0 10,44 14 ? 3 WED" ----三月的每周三的14:10和14:44触发
"0 15 10 ? * MON-FRI" ----每个周一、周二、周三、周四、周五的10:15触发
"0 15 10 15 * ?" 每月15号的10:15触发
"0 15 10 L * ?" 每月的最后一天的10:15触发
"0 15 10 ? * 6L" ----每月最后一个周五的10:15
相关推荐
3. **集成现有技术**:Spring能够很好地与其他技术如ORM框架、日志框架、定时任务框架等协同工作。 4. **模块化**:Spring框架的模块化设计让开发者可以根据项目需求选择合适的模块,减少不必要的代码负担。 5. ...
需要把app部署在多台服务器上,但只能让其中一台服务器的job执行,一台服务器挂了,另一台还能继续执行job,通过网上查找资料,都是java工程的方式,不好部署并测试,经过二天辛苦整合,终于整理成一个单spring web...
以上只是部分核心知识点,实际上Spring Boot还有许多其他特性,如邮件服务、定时任务、缓存管理等。通过思维导图,开发者可以清晰地看到各个知识点之间的关系,有助于理解和记忆,进一步提升开发效率。
基础篇\课件\01、分布式基础&项目环境搭建.pdf ...高级篇\课件\12、定时任务与分布式调度.pdf 高级篇\课件\13、ShardingSphere.pdf 高级篇\课件\14、SpringCloud组件.pdf 高级篇\课件\usingthymeleaf
定时任务是 Spring Boot 应用中常见的需求,通过 `@Scheduled` 注解和 TaskScheduler 接口,开发者可以方便地在应用中安排和管理定时任务。在实际开发中,根据业务需求和项目特点,选择合适的框架和工具是至关重要的...
- **定时任务**:通过 `@Scheduled` 注解或使用 Quartz 等框架实现定时任务。 - **同步与并发控制**:利用 Spring Boot 的并发工具和框架实现线程安全的应用开发。 - **多环境配置**:通过配置文件或 `@Profile` ...
业务模块包括:权限管理,会员管理,角色管理,定时任务管理(调度管理),问答管理,文章管理,共享管理,短信接口管理和邮件系统发送(注册,找回密码,邮件订阅),跨域登录,消息推送,全文检索,前端国际化等等...
### 个人整理的3年以上JAVA开发面试资料 #### 一、线程池涉及的几个类及作用? Java标准库提供了多种线程池实现,通过`java.util.concurrent.Executors`类来创建不同类型的线程池。这些线程池的设计旨在帮助开发者...
SpringBoot实用资料涵盖了许多在开发过程中常用的功能模块,包括日志框架、定时任务、API文档管理、邮件服务、对象关系映射以及Excel处理等。以下将对这些知识点进行详细的介绍: 1. **SpringBoot日志框架使用** ...
`core-context-dao.xml`和`core-context-service.xml`涉及核心模块的DAO和服务,包括菜单、模型管理和定时任务。`ext-context-dao.xml`和`ext-context-service.xml`则涉及到扩展模块,例如采集功能(目前未知具体...
随着项目复杂度的增加,Spring Boot提供的特性将更显其价值,比如数据库集成、缓存管理、定时任务、API文档自动生成等,都能在Spring Boot中找到简便的解决方案。因此,Spring Boot成为了现代Java开发中不可或缺的一...
总体而言,Quartz是一个功能强大且灵活的作业调度框架,它让开发者能够轻松地实现定时任务的调度和管理,而该书中译版的诞生,为中文用户群体提供了一本详细学习和使用Quartz的中文参考资料。通过阅读和使用这本书,...
源码中会展示如何配置和执行定时任务。 9. **日志记录** 日志是任何软件项目的重要组成部分,用于调试和监控。源码中可能包含对log4j或logback的日志配置和使用。 10. **单元测试** 使用JUnit或Mockito进行单元...
学习如何配置和使用Spring Batch,可以处理大量数据的导入导出、定时任务等。 8. **Lesson-code**:这部分可能包含了按照课程进度编写的代码示例,每个章节的代码都会帮助学习者逐步理解并实践Java编程。 9. **...
本仓库用于学习收集整理 掘金 Mr_初晨 Spring Boot2 教程及源码 Mr_初晨教程入口: Mr_初晨码云链接: 从零搭建自己的springboot后台框架 ... 二十一:添加定时任务功能 二十二:添加图片压缩处理功能
它通过预配置各种常见的技术,如数据源、JPA、定时任务等,使得开发者可以即刻进行开发,无需花费大量时间在设置环境上。同时,SpringBoot提供了丰富的starter pom,只需引入相应的依赖,就能自动配置相关的服务。 ...
- 这个注解直接导入了 `SchedulingConfiguration` 配置类,该类定义了与定时任务相关的配置。 3. **第二类:依据条件选择配置类** - 示例:`@EnableAsync` - 通过 `AsyncConfigurationSelector` 类根据不同的...
`cron资料.pdf`可能是关于定时任务的资料,因为调查问卷系统可能需要定期发送提醒或者处理统计数据,这通常会用到cron表达式来配置定时任务。 `survey.pdm`是数据库模型的文件,通常由PowerDesigner等工具生成,它...