2022年任务调度框架Quartz .pdf

上传人:Che****ry 文档编号:30533262 上传时间:2022-08-06 格式:PDF 页数:20 大小:297.38KB
返回 下载 相关 举报
2022年任务调度框架Quartz .pdf_第1页
第1页 / 共20页
2022年任务调度框架Quartz .pdf_第2页
第2页 / 共20页
点击查看更多>>
资源描述

《2022年任务调度框架Quartz .pdf》由会员分享,可在线阅读,更多相关《2022年任务调度框架Quartz .pdf(20页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、任务调度框架 Quartz文档概述各种企业应用几乎都会碰到任务调度的需求,就拿论坛来说: 每隔半个小时生成精华文章的 RSS 文件,每天凌晨统计论坛用户的积分排名,每隔30 分钟执行锁定用户解锁任务。对于一个典型的 MIS 系统来说,在每月 1 号凌晨统计上个月各部门的业务数据生成月报表,每半个小时查询用户是否已经有快到期的待处理业务,这样的例子俯拾皆是,不胜枚举。任务调度本身涉及到多线程并发、运行时间规则制定和解析、场景保持与恢复、线程池维护等诸多方面的工作。 如果直接使用自定义线程这种刀耕火种的原始办法,开发任务调度程序是一项颇具挑战性的工作。Java 开源的好处就是:领域问题都能找到现成

2、的解决方案。OpenSymphony所提供的 Quartz自 2001 年发布版本以来已经被众多项目作为任务调度的解决方案, Quartz在提供巨大灵活性的同时并未牺牲其简单性,它所提供的强大功能使你可以应付绝大多数的调度需求。Quartz 在开源任务调度框架中的翘首,它提供了强大任务调度机制,难能可贵的是它同时保持了使用的简单性。Quartz 允许开发人员灵活地定义触发器的调度时间表,并可以对触发器和任务进行关联映射。此外, Quartz提供了调度运行环境的持久化机制,可以保存并恢复调度现场,即使系统因故障关闭,任务调度现场数据并不会丢失。此外,Quartz还提供了组件式的侦听器、各种插件、

3、线程池等功能。了解 Quartz体系结构Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这 3 个核心的概念, 并在 org.quartz通过接口和类对重要的这些核心概念进行描述:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 20 页 - - - - - - - - - Job :是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionC

4、ontext类提供了调度上下文的各种信息。Job 运行时的信息保存在JobDataMap实例中; JobDetail :Quartz在每次执行 Job 时,都重新创建一个Job 实例,所以它不直接接受一个 Job 的实例,相反它接收一个Job 实现类,以便运行时通过newInstance()的反射机制实例化Job 。因此需要通过一个类来描述Job 的实现类及其它相关的静态信息, 如 Job 名字、描述、关联监听器等信息, JobDetail承担了这一角色。通过该类的构造函数可以更具体地了解它的功用:JobDetail(java.lang.String name, java.lang.Strin

5、g group, java.lang.Class jobClass),该构造函数要求指定 Job 的实现类,以及任务在Scheduler中的组名和 Job 名称; Trigger:是一个类,描述触发Job 执行的时间触发规则。主要有SimpleTrigger和 CronTrigger这两个子类。 当仅需触发一次或者以固定时间间隔周期执行, SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron 表达式定义出各种复杂时间规则的调度方案:如每早晨 9:00执行,周一、周三、周五下午 5:00执行等; Calendar:org.quartz.Calendar和 java

6、.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合 java.util.Calendar代表一个日历时间点,无特殊说明后面的 Calendar即指 org.quartz.Calendar)。一个 Trigger可以和多个 Calendar关联,以便排除或包含某些时间点。假设,我们安排每周星期一早上10:00执行任务,但是如果碰到法定的节日,任务则不执行,这时就需要在 Trigger触发机制的基础上使用Calendar进行定点排除。针对不同时间段类型,Quartz在 org.quartz

7、.impl.calendar包下提供了若干个 Calendar的实现类,如 AnnualCalendar、MonthlyCalendar、WeeklyCalendar分别针对每年、每月和每周进行定义; Scheduler :代表一个 Quartz的独立运行容器, Trigger和 JobDetail可以注册到 Scheduler中,两者在 Scheduler中拥有各自的组及名称, 组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须唯一,名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整

8、理 - - - - - - - 第 2 页,共 20 页 - - - - - - - - - JobDetail的组和名称也必须唯一 (但可以和 Trigger的组和名称相同, 因为它们是不同类型的)。 Scheduler定义了多个接口方法,允许外部通过组及名称访问和控制容器中Trigger和 JobDetail。Scheduler可以将 Trigger绑定到某一 JobDetail中, 这样当 Trigger触发时,对应的 Job 就被执行。一个Job 可以对应多个 Trigger ,但一个 Trigger只能对应一个 Job 。可以通过 SchedulerFactory创建一个 Sched

9、uler实例。Scheduler拥有一个 SchedulerContext,它类似于 ServletContext,保存着 Scheduler上下文信息,Job 和 Trigger都可以访问 SchedulerContext内的信息。 SchedulerContext内部通过一个 Map ,以键值对的方式维护这些上下文数据,SchedulerContext为保存和获取数据提供了多个put() 和 getXxx()的方法。可以通过 Scheduler# getContext()获取对应的 SchedulerContext实例; ThreadPool :Scheduler使用一个线程池作为任务运行

10、的基础设施,任务通过共享线程池中的线程提高运行效率。Job 有一个 StatefulJob子接口,代表有状态的任务, 该接口是一个没有方法的标签接口,其目的是让Quartz知道任务的类型,以便采用不同的执行方案。无状态任务在执行时拥有自己的JobDataMap拷贝,对 JobDataMap的更改不会影响下次的执行。而有状态任务共享共享同一个JobDataMap实例,每次任务执行对 JobDataMap所做的更改会保存下来, 后面的执行可以看到这个更改,也即每次执行任务后都会对后面的执行发生影响。正因为这个原因,无状态的Job 可以并发执行,而有状态的StatefulJob不能并发执行,这意味着

11、如果前次的StatefulJob还没有执行完毕,下一次的任务将阻塞等待, 直到前次任务执行完毕。 有状态任务比无状态任务需要考虑更多的因素,程序往往拥有更高的复杂度, 因此除非必要, 应该尽量使用无状态的Job 。如果 Quartz使用了数据库持久化任务调度信息,无状态的JobDataMap仅会在 Scheduler注册任务时保持一次,而有状态任务对应的JobDataMap在每次执行任务后都会进行保存。Trigger自身也可以拥有一个JobDataMap,其关联的 Job 可以通过JobExecutionContext#getTrigger().getJobDataMap()获取 Trigge

12、r中的名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 20 页 - - - - - - - - - JobDataMap。不管是有状态还是无状态的任务,在任务执行期间对Trigger的 JobDataMap所做的更改都不会进行持久, 也即不会对下次的执行产生影响。Quartz拥有完善的事件和监听体系,大部分组件都拥有事件,如任务执行前事件、任务执行后事件、触发器触发前事件、触发后事件、调度器开始事件、关闭事件等等,可以注册相应的监听器处理感兴趣的事件。图 1 描述了 Sc

13、heduler的内部组件结构, SchedulerContext提供 Scheduler全局可见的上下文信息,每一个任务都对应一个JobDataMap,虚线表达的JobDataMap表示对应有状态的任务:图 1 Scheduler结构图一个 Scheduler可以拥有多个 Triger组和多个 JobDetail组,注册 Trigger和 JobDetail时,如果不显式指定所属的组,Scheduler将放入到默认组中,默认组的组名为 Scheduler.DEFAULT_GROUP。组名和名称组成了对象的全名,同一类型对象的全名不能相同。Scheduler本身就是一个容器,它维护着Quartz

14、的各种组件并实施调度的规则。Scheduler还拥有一个线程池,线程池为任务提供执行线程这比执行任务时简单地创建一个新线程要拥有更高的效率,同时通过共享节约资源的占用。通过线程池组件的支持,对于繁忙度高、压力大的任务调度,Quartz将可以提供良好的伸缩性。提示:Quartz完整下载包 examples目录下拥有 10 多个实例,它们是快速掌握 Quartz应用很好的实例。使用 SimpleTrigger 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 20 页 - -

15、- - - - - - - SimpleTrigger拥有多个重载的构造函数,用以在不同场合下构造出对应的实例: SimpleTrigger(String name, String group):通过该构造函数指定Trigger所属组和名称; SimpleTrigger(String name, String group, Date startTime):除指定Trigger所属组和名称外,还可以指定触发的开发时间; SimpleTrigger(String name, String group, Date startTime, Date endTime, int repeatCount, l

16、ong repeatInterval):除指定以上信息外,还可以指定结束时间、重复执行次数、时间间隔等参数; SimpleTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, int repeatCount, long repeatInterval):这是最复杂的一个构造函数,在指定触发参数的同时,还通过 jobGroup和 jobName,让该 Trigger和 Scheduler中的某个任务关联起来。通过实现org.quartz.Job 接口,可以使

17、 Java 类化身为可调度的任务。 代码清单 1 提供了 Quartz 任务的一个示例:代码清单 1 SimpleJob:简单的 Job 实现类package com.baobaotao.basic.quartz; import java.util.Date; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class SimpleJob implements Job 实例 Job 接口方法public void execu

18、te(JobExecutionContext jobCtx)throws JobExecutionException System.out.println(jobCtx.getTrigger().getName()+ triggered. time is: + (new Date(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 20 页 - - - - - - - - - 这个类用一条非常简单的输出语句实现了Job 接口的execute(JobExecutionCo

19、ntext context) 方法,这个方法可以包含想要执行的任何代码。下面,我们通过SimpleTrigger对 SimpleJob进行调度:代码清单 2 SimpleTriggerRunner:使用 SimpleTrigger进行调度package com.baobaotao.basic.quartz; import java.util.Date; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerFactory; import org.quartz.SimpleTrig

20、ger; import org.quartz.impl.StdSchedulerFactory; public class SimpleTriggerRunner public static void main(String args) try 创建一个 JobDetail实例,指定SimpleJobJobDetail jobDetail = new JobDetail(job1_1,jGroup1, SimpleJob.class); 通过 SimpleTrigger定义调度规则:马上启动,每2 秒运行一次,共运行100 次SimpleTrigger simpleTrigger = new

21、SimpleTrigger(trigger1_1,tgroup1); simpleTrigger.setStartTime(new Date(); simpleTrigger.setRepeatInterval(2000); simpleTrigger.setRepeatCount(100); 通过 SchedulerFactory获取一个调度器实例SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); schedu

22、ler.scheduleJob(jobDetail, simpleTrigger); 注册并进行调度scheduler.start();调度启动 catch (Exception e) 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 20 页 - - - - - - - - - e.printStackTrace(); 首先在处通过 JobDetail封装 SimpleJob ,同时指定 Job 在 Scheduler中所属组及名称,这里,组名为jGroup1 ,而名称为

23、 job1_1 。在处创建一个 SimpleTrigger实例, 指定该 Trigger在 Scheduler中所属组及名称。接着设置调度的时间规则。最后,需要创建 Scheduler实例,并将 JobDetail和 Trigger实例注册到Scheduler中。这里,我们通过StdSchedulerFactory获取一个 Scheduler实例,并通过 scheduleJob(JobDetail jobDetail, Trigger trigger)完成两件事:1) 将 JobDetail和 Trigger注册到 Scheduler中;2) 将 Trigger指派给 JobDetail,将两

24、者关联起来。当 Scheduler启动后, Trigger将定期触发并执行SimpleJob的execute(JobExecutionContext jobCtx)方法,然后每10 秒重复一次,直到任务被执行100 次后停止。还可以通过 SimpleTrigger的 setStartTime(java.util.Date startTime)和setEndTime(java.util.Date endTime)指定运行的时间范围,当运行次数和时间范围冲突时,超过时间范围的任务运行不被执行。如可以通过simpleTrigger.setStartTime(new Date(System.curre

25、ntTimeMillis() + 60000L)指定 60 秒钟以后开始。除了通过 scheduleJob(jobDetail, simpleTrigger)建立 Trigger和JobDetail的关联,还有另外一种关联Trigger和 JobDetail的方式:JobDetail jobDetail = new JobDetail(job1_1,jGroup1, SimpleJob.class); SimpleTrigger simpleTrigger = new SimpleTrigger(trigger1_1,tgroup1); 名师资料总结 - - -精品资料欢迎下载 - - - -

26、 - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 20 页 - - - - - - - - - simpleTrigger.setJobGroup(jGroup1);-1 :指定关联的 Job 组名simpleTrigger.setJobName(job1_1);-2 :指定关联的Job 名称scheduler.addJob(jobDetail, true); 注册 JobDetailscheduler.scheduleJob(simpleTrigger); 注册指定了关联 JobDetail的Trigger在这种方式中,Tri

27、gger通过指定 Job 所属组及 Job 名称, 然后使用 Scheduler的 scheduleJob(Trigger trigger)方法注册 Trigger 。有两个值得注意的地方:通过这种方式注册的Trigger实例必须已经指定Job 组和 Job 名称,否则调用注册 Trigger的方法将抛出异常;引用的 JobDetail对象必须已经存在于Scheduler中。也即,代码中、和的先后顺序不能互换。在构造 Trigger实例时,可以考虑使用 org.quartz.TriggerUtils工具类,该工具类不但提供了众多获取特定时间的方法,还拥有众多获取常见Trigger的方法, 如

28、makeSecondlyTrigger(String trigName)方法将创建一个每秒执行一次的 Trigger ,而 makeWeeklyTrigger(String trigName, int dayOfWeek, int hour, int minute)将创建一个每星期某一特定时间点执行一次的Trigger 。而 getEvenMinuteDate(Date date)方法将返回某一时间点一分钟以后的时间。使用 CronTrigger CronTrigger 能够提供比SimpleTrigger 更有具体实际意义的调度方案,调度规则基于Cron 表达式,CronTrigger 支持

29、日历相关的重复时间间隔(比如每月第一个周一执行),而不是简单的周期时间间隔。因此,相对于SimpleTrigger而言, CronTrigger在使用上也要复杂一些。Cron表达式Quartz使用类似于 Linux 下的 Cron 表达式定义时间规则, Cron 表达式由 6或 7 个由空格分隔的时间字段组成,如表1 所示:表 1 Cron表达式时间字段名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 20 页 - - - - - - - - - 位置时间域名允许值允许的特

30、殊字符1 秒0-59 , - * / 2 分钟0-59 , - * / 3 小时0-23 , - * / 4 日期1-31 , - * ? / L W C 5 月份1-12 , - * / 6 星期1-7 , - * ? / L C # 7 年(可选) 空值1970-2099 , - * / Cron 表达式的时间字段除允许设置数值外,还可使用一些特殊的字符,提供列表、范围、通配符等功能,细说如下: 星号(*) :可用在所有字段中,表示对应时间域的每一个时刻,例如,* 在分钟字段时,表示 “ 每分钟 ” ; 问号( ?):该字符只在日期和星期字段中使用,它通常指定为“ 无意义的值 ” ,相当于

31、点位符; 减号(-) :表达一个范围,如在小时字段中使用“ 10 -12” ,则表示从 10 到 12点,即 10,11,12; 逗号(,) :表达一个列表值, 如在星期字段中使用 “ MON,WED,FRI” ,则表示星期一,星期三和星期五; 斜杠(/) :x/y 表达一个等步长序列, x 为起始值, y 为增量步长值。如在分钟字段中使用 0/15 ,则表示为 0,15,30和 45 秒,而 5/15在分钟字段中表示5,20,35,50,你也可以使用 */y ,它等同于 0/y ;L :该字符只在日期和星期字段中使用,代表“ Last ”的意思,但它在两个字段中意思不同。 L 在日期字段中,

32、表示这个月份的最后一天,如一月的31 号,非闰年二月的 28 号;如果 L 用在星期中,则表示星期六,等同于7。但是,如果L 出现在星期字段里,而且在前面有一个数值X,则表示 “ 这个月的最后 X 天” ,例如, 6L 表示该月的最后星期五;名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 20 页 - - - - - - - - - W :该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如 15W 表示离该月 15 号最近的工作日,如果该月15

33、 号是星期六,则匹配 14 号星期五;如果 15 日是星期日,则匹配16 号星期一;如果 15号是星期二,那结果就是 15 号星期二。但必须注意关联的匹配日期不能够跨月,如你指定 1W ,如果 1 号是星期六,结果匹配的是3 号星期一,而非上个月最后的那天。 W 字符串只能指定单一日期,而不能指定日期范围; LW组合:在日期字段可以组合使用LW ,它的意思是当月的最后一个工作日; 井号(#) :该字符只能在星期字段中使用,表示当月某个工作日。 如 6#3表示当月的第三个星期五 (6 表示星期五,#3 表示当前的第三个 ) , 而 4#5 表示当月的第五个星期三,假设当月没有第五个星期三,忽略不

34、触发; C :该字符只在日期和星期字段中使用,代表“ Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5 日以后的第一天。 1C 在星期字段中相当于星期日后的第一天。Cron 表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。表 2 下面给出一些完整的Cron 表示式的实例:表 2 Cron表示式示例表示式说明0 0 12 * * ? 每天 12 点运行0 15 10 ? * * 每天 10:15运行0 15 10 * * ? 每天 10:15运行0 15 10 * * ? * 每天 10:15

35、运行0 15 10 * * ? 2008 在 2008 年的每天 10 :15 运行0 * 14 * * ? 每天 14 点到 15 点之间每分钟运行一次,开始于 14:00 ,结束于 14:59 。0 0/5 14 * * ? 每天 14 点到 15 点每 5 分钟运行一次,开始于 14:00 ,结束于 14:55 。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 20 页 - - - - - - - - - 0 0/5 14,18 * * ? 每天 14 点到 15

36、 点每 5 分钟运行一次,此外每天 18 点到 19 点每 5 钟也运行一次。0 0-5 14 * * ? 每天 14:00点到 14:05 , 每分钟运行一次。0 10,44 14 ? 3 WED 3 月每周三的 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分运行。0 15 10 ? * 6L 2007-2009 在 2007,2

37、008,2009年每个月的最后一个星期五的 10:15分运行。0 15 10 ? * 6#3 每月第三个星期五的10:15分运行。CronTrigger实例下面,我们使用 CronTrigger对 SimpleJob进行调度, 通过 Cron 表达式制定调度规则,让它每5 秒钟运行一次:代码清单 3 CronTriggerRunner:使用 CronTrigger进行调度package com.baobaotao.basic.quartz; import org.quartz.CronExpression; import org.quartz.CronTrigger; import org.q

38、uartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerFactory; import org.quartz.impl.StdSchedulerFactory; public class CronTriggerRunner public static void main(String args) try 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 20 页 - - - - -

39、- - - - JobDetail jobDetail = new JobDetail(job1_2, jGroup1,SimpleJob.class); -1 :创建 CronTrigger,指定组及名称CronTrigger cronTrigger = new CronTrigger(trigger1_2, tgroup1); CronExpression cexp = new CronExpression(0/5 * * * * ?);-2 :定义 Cron表达式cronTrigger.setCronExpression(cexp); -3 :设置 Cron表达式SchedulerFac

40、tory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.scheduleJob(jobDetail, cronTrigger); scheduler.start(); / catch (Exception e) e.printStackTrace(); 运行 CronTriggerRunner,每 5 秒钟将触发运行SimpleJob一次。默认情况下 Cron 表达式对应当前的时区,可以通过CronTriggerRunn

41、er的setTimeZone(java.util.TimeZone timeZone)方法显式指定时区。 你还也可以通过 setStartTime(java.util.Date startTime)和setEndTime(java.util.Date endTime)指定开始和结束的时间。在代码清单 3 的处需要通过Thread.currentThread.sleep()的方式让主线程睡眠,以便调度器可以继续工作执行任务调度。否则在调度器启动后, 因为主线程马上退出, 也将同时引起调度器关闭, 调度器中的任务都将相应销毁,这将导致看不到实际的运行效果。 在单元测试的时候, 让主线程睡眠经常使用

42、的办法。对于某些长周期任务调度的测试,你可以简单地调整操作系统时间进行模拟。使用 Calendar 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 20 页 - - - - - - - - - 在实际任务调度中,我们不可能一成不变地按照某个周期性的调度规则运行任务,必须考虑到实现生活中日历上特定日期,就象习惯了大男人作风的人在2月 14 号也会有不同表现一样。下面,我们安排一个任务, 每小时运行一次, 并将五一节和国际节排除在外,其代码如代码清单 4 所示:代码清单 4

43、 CalendarExample:使用 Calendar package com.baobaotao.basic.quartz; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import org.quartz.impl.calendar.AnnualCalendar; import org.quartz.TriggerUtils; public class CalendarExample public static void main(String args) thr

44、ows Exception SchedulerFactory sf = new StdSchedulerFactory(); Scheduler scheduler = sf.getScheduler(); 法定节日是以每年为周期的,所以使用AnnualCalendar AnnualCalendar holidays = new AnnualCalendar(); 五一劳动节Calendar laborDay = new GregorianCalendar(); laborDay.add(Calendar.MONTH,5); laborDay.add(Calendar.DATE,1); hol

45、idays.setDayExcluded(laborDay, true ); -1 :排除的日期, 如果设置为 false则为包含国庆节Calendar nationalDay = new GregorianCalendar(); nationalDay.add(Calendar.MONTH,10); nationalDay.add(Calendar.DATE,1); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 20 页 - - - - - - - - - holi

46、days.setDayExcluded(nationalDay, true ); -1 :排除该日期scheduler.addCalendar(holidays, holidays, false, false);向Scheduler注册日历Date runDate = TriggerUtils.getDateOf(0,0, 10, 1, 4);4 月 1 号 上午10 点JobDetail job = new JobDetail(job1, group1, SimpleJob.class); SimpleTrigger trigger = new SimpleTrigger(trigger1,

47、 group1, runDate, null, SimpleTrigger.REPEAT_INDEFINITELY, 60L * 60L * 1000L); trigger.setCalendarName(holidays);让 Trigger应用指定的日历规则scheduler.scheduleJob(job, trigger); scheduler.start(); / 实际应用中主线程不能停止,否则Scheduler得不到执行,此处从略 由于节日是每年重复的,所以使用org.quartz.Calendar的 AnnualCalendar实现类,通过、的代码,指定五一和国庆两个节日并通过A

48、nnualCalendar#setDayExcluded(Calendar day, boolean exclude)方法添加这两个日期。 exclude为 true 时表示排除指定的日期,如果为false 时表示包含指定的日期。在定制好 org.quartz.Calendar后,还需要通过Scheduler#addCalendar(String calName, Calendar calendar, boolean replace, boolean updateTriggers)进行注册,如果 updateTriggers为 true ,Scheduler中已引用 Calendar的 Tri

49、gger将得到更新,如所示。在处,我们让一个Trigger指定使用 Scheduler中代表节日的 Calendar ,这样 Trigger就会避开五一和国庆这两个特殊日子了。任务调度信息存储名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 20 页 - - - - - - - - - 在默认情况下 Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能, 因为内存中数据访问最快。 不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会

50、丢失。比如我们希望安排一个执行100 次的任务,如果执行到50 次时系统崩溃了,系统重启时任务的执行计数器将从0 开始。在大多数实际的应用中,我们往往并不需要保存任务调度的现场数据,因为很少需要规划一个指定执行次数的任务。对于仅执行一次的任务来说, 其执行条件信息本身应该是已经持久化的业务数据(如锁定到期解锁任务, 解锁的时间应该是业务数据) ,当执行完成后, 条件信息也会相应改变。当然调度现场信息不仅仅是记录运行次数,还包括调度规则、JobDataMap中的数据等等。如果确实需要持久化任务调度信息,Quartz允许你通过调整其属性文件,将这些信息保存到数据库中。 使用数据库保存任务调度信息后

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁