分享
分享赚钱 收藏 举报 版权申诉 / 19

类型Quartz入门教程.doc

  • 上传人:scg750829
  • 文档编号:7232500
  • 上传时间:2019-05-10
  • 格式:DOC
  • 页数:19
  • 大小:112KB
  • 配套讲稿:

    如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。

    特殊限制:

    部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。

    关 键  词:
    Quartz入门教程.doc
    资源描述:

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

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

    3、件、线程池等功能。了解 Quartz 体系结构Quartz 对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这 3 个核心的概念,并在 org.quartz 通过接口和类对重要的这些核心概念进行描述:Job:是一个接口,只有一个方法 void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext 类提供了调度上下文的各种信息。Job 运行时的信息保存在 JobDataMap 实例中;JobDetail:Quartz 在每次执行 Job 时,都重新创建一个 Job 实例,所以它不直接接受一个

    4、 Job 的实例,相反它接收一个 Job 实现 类,以便运行时通过newInstance()的反射机制实例化 Job。因此需要通过一个类来描述 Job 的实现类及其它相关的静态信息,如 Job 名字、描 述、关联监听器等信息,JobDetail 承担了这一角色。通过该类的构造函数可以更具体地了解它的功用:JobDetail(java.lang.String name, java.lang.String group, java.lang.Class jobClass),该构造函数要求指定 Job 的实现类,以及任务在Scheduler 中的组名和 Job 名称;Trigger:是一个类,描述触发

    5、 Job 执行的时间触发规则。主要有SimpleTrigger 和 CronTrigger 这两个子类。当仅需触 发一次或者以固定时间间隔周期执行,SimpleTrigger 是最适合的选择;而 CronTrigger 则可以通过Cron 表达式定义出各种复杂时间规 则的调度方案:如每早晨 9:00 执行,周一、周三、周五下午 5:00 执行等;Calendar:org.quartz.Calendar 和 java.util.Calendar 不同,它是一些日历特定时间点的集合(可以简 单地将 org.quartz.Calendar 看作java.util.Calendar 的集合java.u

    6、til.Calendar 代表一个日历时 间点,无特殊说明后面的 Calendar 即指 org.quartz.Calendar)。一个 Trigger 可以和多个 Calendar 关联,以便排除或 包含某些时间点。假设,我们安排每周星期一早上 10:00 执行任务,但是如果碰到法定的节日,任务则不执行,这时就需要在 Trigger 触发机制的基础上使用 Calendar 进行定点排除。针对不同时间段类型,Quartz 在 org.quartz.impl.calendar 包下提供了若干个 Calendar 的实现类,如AnnualCalendar、MonthlyCalendar、Weekl

    7、yCalendar 分别针对每年、每月和每周进行定义;Scheduler:代表一个 Quartz 的独立运行容器,Trigger 和 JobDetail 可以注册到 Scheduler 中,两者在 Scheduler 中拥有各自的组及名称,组及名称是Scheduler 查找定位容器中某一对象的依据,Trigger 的组及名称必须唯 一,JobDetail 的组和名称也必须唯一(但可以和 Trigger 的组和名称相同,因为它们是不同类型的)。Scheduler 定义了多个接口方法, 允许外部通过组及名称访问和控制容器中 Trigger 和 JobDetail。Scheduler 可以将 Tri

    8、gger 绑定到某一 JobDetail 中,这样当 Trigger 触发时,对应的 Job 就被执行。一个 Job 可以对应 多个 Trigger,但一个 Trigger 只能对应一个 Job。可以通过 SchedulerFactory 创建一个 Scheduler 实例。 Scheduler 拥有一个 SchedulerContext,它类似于 ServletContext,保存着Scheduler 上下文信息,Job 和 Trigger 都可以访问 SchedulerContext 内的信息。SchedulerContext 内部通过一个 Map,以键值对的方式维护这些上下 文数据,Sc

    9、hedulerContext 为保存和获取数据提供了多个 put()和 getXxx()的方法。可以通过 Scheduler# getContext()获取对应的 SchedulerContext 实例;Quartz 任务调度快速入门 2ThreadPool:Scheduler 使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。Job 有一个 StatefulJob 子接口,代表有状态的任务,该接口是一个没有方法的标签接口,其目的是让 Quartz 知道任务的类型,以便采用 不同的执行方案。无状态任务在执行时拥有自己的 JobDataMap 拷贝,对 JobData

    10、Map 的更改不会影响下次的执行。而有状态任务共享共享同一个 JobDataMap 实例,每次任务执行对 JobDataMap 所做的更改会保存下来,后面的执行可以看到这个更改,也即每次执行任务后都会对后面的执行 发生影响。正因为这个原因,无状态的 Job 可以并发执行,而有状态的 StatefulJob 不能并发执行,这意味着如果前次的 StatefulJob 还没有执 行完毕,下一次的任务将阻塞等待,直到前次任务执行完毕。有状态任务比无状态任务需要考虑更多的因素,程序往往拥有更高的复杂度,因此除非必要,应该尽量 使用无状态的Job。如果 Quartz 使用了数据库持久化任务调度信息,无状态

    11、的 JobDataMap 仅会在Scheduler 注册任务时保持一次,而有状态任务对应的 JobDataMap 在每次执行任务后都会进行保存。Trigger 自身也可以拥有一个 JobDataMap,其关联的 Job 可以通过 JobExecutionContext#getTrigger().getJobDataMap()获取 Trigger 中的JobDataMap。不管 是有状态还是无状态的任务,在任务执行期间对 Trigger的 JobDataMap 所做的更改都不会进行持久,也即不会对下次的执行产生影响。Quartz 拥有完善的事件和监听体系,大部分组件都拥有事件,如任务执行前事件、

    12、任务执行后事件、触发器触发前事件、触发后事件、调度器开始事件、关闭事件等等,可以注册相应的监听器处理感兴趣的事件。图 1 描述了 Scheduler 的内部组件结构,SchedulerContext 提供 Scheduler 全局可见的上下文信息,每一个任务都对应一个 JobDataMap,虚线表达的JobDataMap 表示对应有状态的任务:图 1 Scheduler 结构图一个 Scheduler 可以拥有多个 Triger 组和多个 JobDetail 组,注册 Trigger和 JobDetail 时,如果不显式指定所属的 组,Scheduler 将放入到默认组中,默认组的组名为 Sc

    13、heduler.DEFAULT_GROUP。组名和名称组成了对象的全名,同一类型对象的 全名不能相同。Scheduler 本身就是一个容器,它维护着 Quartz 的各种组件并实施调度的规则。Scheduler 还拥有一个线程池,线程池为任务提供执 行线程这比执行任务时简单地创建一个新线程要拥有更高的效率,同时通过共享节约资源的占用。通过线程池组件的支持,对于繁忙度高、压力大的任务调 度,Quartz 将可以提供良好的伸缩性。提示: Quartz 完整下载包 examples 目录下拥有 10 多个实例,它们是快速掌握 Quartz 应用很好的实例。使用 SimpleTriggerSimple

    14、Trigger 拥有多个重载的构造函数,用以在不同场合下构造出对应的实例: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, long repeatInterval):

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

    16、码清单 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 execute(JobExecutionContext j

    17、obCtx)throws JobExecutionException System.out.println(jobCtx.getTrigger().getName()+ “ triggered. time is:“ + (new Date();这个类用一条非常简单的输出语句实现了 Job 接口的execute(JobExecutionContext context) 方法,这个方法可以包含想要执行的任何代码。下面,我们通过 SimpleTrigger 对 SimpleJob 进行调度:代码清单 2 SimpleTriggerRunner:使用 SimpleTrigger 进行调度package

    18、 com.baobaotao.basic.quartz;import java.util.Date;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerFactory;import org.quartz.SimpleTrigger;import org.quartz.impl.StdSchedulerFactory;public class SimpleTriggerRunner public static void main(String args) try 创建一个 JobDe

    19、tail 实例,指定 SimpleJobJobDetail jobDetail = new JobDetail(“job1_1“,“jGroup1“, SimpleJob.class);通过 SimpleTrigger 定义调度规则:马上启动,每 2 秒运行一次,共运行100 次SimpleTrigger simpleTrigger = new SimpleTrigger(“trigger1_1“,“tgroup1“);simpleTrigger.setStartTime(new Date();simpleTrigger.setRepeatInterval(2000);simpleTrigge

    20、r.setRepeatCount(100);通过 SchedulerFactory 获取一个调度器实例SchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();scheduler.scheduleJob(jobDetail, simpleTrigger); 注册并进行调度scheduler.start();调度启动 catch (Exception e) e.printStackTrace();首先在处通过 JobDeta

    21、il 封装 SimpleJob,同时指定 Job 在 Scheduler 中所属组及名称,这里,组名为 jGroup1,而名称为 job1_1。在处创建一个 SimpleTrigger 实例,指定该 Trigger 在 Scheduler 中所属组及名称。接着设置调度的时间规则。最后,需要创建 Scheduler 实例,并将 JobDetail 和 Trigger 实例注册到Scheduler 中。这里,我们通过 StdSchedulerFactory 获取一个 Scheduler 实例,并通过 scheduleJob(JobDetail jobDetail, Trigger trigger)

    22、完成两件事:1)将 JobDetail 和 Trigger 注册到 Scheduler 中;2)将 Trigger 指派给 JobDetail,将两者关联起来。当 Scheduler 启动后,Trigger 将定期触发并执行 SimpleJob 的execute(JobExecutionContext jobCtx)方法,然后每 10 秒重复一次,直到任务被执行 100 次后停止。还可以通过 SimpleTrigger 的 setStartTime(java.util.Date startTime)和setEndTime(java.util.Date endTime)指定运行的时间范围,当运行

    23、次数和时间范围冲突时,超过时间范围的任务运行不被执行。如可以通过 simpleTrigger.setStartTime(new Date(System.currentTimeMillis() + 60000L)指定 60 秒钟以后开始。除了通过 scheduleJob(jobDetail, simpleTrigger)建立 Trigger 和 JobDetail的关联,还有另外一种关联 Trigger 和 JobDetail 的方式:JobDetail jobDetail = new JobDetail(“job1_1“,“jGroup1“, SimpleJob.class);SimpleTr

    24、igger simpleTrigger = new SimpleTrigger(“trigger1_1“,“tgroup1“);simpleTrigger.setJobGroup(“jGroup1“);-1:指定关联的 Job 组名simpleTrigger.setJobName(“job1_1“);-2:指定关联的 Job 名称scheduler.addJob(jobDetail, true); 注册 JobDetailscheduler.scheduleJob(simpleTrigger); 注册指定了关联 JobDetail 的Trigger在这种方式中,Trigger 通过指定 Job

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

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

    27、的重复时间间隔(比如每月第一个周一执行),而不是简单的周期时间间隔。因此,相对于SimpleTrigger 而 言,CronTrigger 在使用上也要复杂一些。Cron 表达式Quartz 使用类似于 Linux 下的 Cron 表达式定义时间规则,Cron 表达式由 6 或7 个由空格分隔的时间字段组成,如表 1 所示:表 1 Cron 表达式时间字段位置 时间域名 允许值 允许的特殊字符1 秒 0-59 , - * /2 分钟 0-59 , - * /3 小时 0-23 , - * /4 日期 1-31 , - * ? / L W C 5 月份 1-12 , - * /6 星期 1-7

    28、, - * ? / L C #7 年(可选) 空值 1970-2099 , - * /Cron 表达式的时间字段除允许设置数值外,还可使用一些特殊的字符,提供列表、范围、通配符等功能,细说如下:星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如,*在分钟字段时,表示“每分钟”;问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从 10 到12 点,即 10,11,12;逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五;斜杠(/)

    29、:x/y 表达一个等步长序列,x 为起始值,y 为增量步长值。如在分钟字段中使用 0/15,则表示为 0,15,30 和 45 秒,而 5/15 在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于 0/y;L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L 在日期字段中,表示这个月份的最后一天,如一月的 31 号,非闰年二月的 28 号;如果 L 用在星期中,则表示星期六,等同于 7。但是,如果 L 出现在星期字段里,而且在前面有一个数值 X,则表示“这个月的最后 X天”,例如,6L 表示该月的最后星期五;W:该字符只能出现在日期字段里,是

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

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

    32、每天 10:15 运行“0 15 10 * * ?“ 每天 10:15 运行“0 15 10 * * ? *“ 每天 10:15 运行“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。“0 0/5 14,18 * * ?“ 每天 14 点到 15 点每 5 分钟运行一次,此外每天 18 点到 19 点每 5 钟也运行一次。“0 0

    33、-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,2008,2009 年每个月的最后一个星期五的 1

    34、0: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.quartz.JobDetail;i

    35、mport org.quartz.Scheduler;import org.quartz.SchedulerFactory;import org.quartz.impl.StdSchedulerFactory;public class CronTriggerRunner public static void main(String args) try JobDetail jobDetail = new JobDetail(“job1_2“, “jGroup1“,SimpleJob.class);-1:创建 CronTrigger,指定组及名称CronTrigger cronTrigger =

    36、new CronTrigger(“trigger1_2“, “tgroup1“);CronExpression cexp = new CronExpression(“0/5 * * * * ?“);-2:定义Cron 表达式cronTrigger.setCronExpression(cexp);-3:设置 Cron 表达式SchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();scheduler.scheduleJob(

    37、jobDetail, cronTrigger);scheduler.start();/ catch (Exception e) e.printStackTrace();运行 CronTriggerRunner,每 5 秒钟将触发运行 SimpleJob 一次。默认情况下Cron 表达式对应当前的时区,可以通过 CronTriggerRunner 的setTimeZone(java.util.TimeZone timeZone)方法显式指定时区。你还也可以通过 setStartTime(java.util.Date startTime)和setEndTime(java.util.Date end

    38、Time)指定开始和结束的时间。在代码清单 3 的处需要通过 Thread.currentThread.sleep()的方式让主线程睡眠,以便调度器可以继续工作执行任务调度。 否则在调度器启动后,因为主线程马上退出,也将同时引起调度器关闭,调度器中的任务都将相应销毁,这将导致看不到实际的运行效果。在单元测试的时候,让主 线程睡眠经常使用的办法。对于某些长周期任务调度的测试,你可以简单地调整操作系统时间进行模拟。使用 Calendar在实际任务调度中,我们不可能一成不变地按照某个周期性的调度规则运行任务,必须考虑到实现生活中日历上特定日期,就象习惯了大男人作风的人在 2月 14 号也会有不同表现

    39、一样。下面,我们安排一个任务,每小时运行一次,并将五一节和国际节排除在外,其代码如代码清单 4 所示:代码清单 4 CalendarExample:使用 Calendarpackage 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 Calend

    40、arExample public static void main(String args) throws Exception SchedulerFactory sf = new StdSchedulerFactory();Scheduler scheduler = sf.getScheduler();法定节日是以每年为周期的,所以使用 AnnualCalendarAnnualCalendar holidays = new AnnualCalendar();五一劳动节Calendar laborDay = new GregorianCalendar();laborDay.add(Calenda

    41、r.MONTH,5);laborDay.add(Calendar.DATE,1);holidays.setDayExcluded(laborDay, true); -1:排除的日期,如果设置为false 则为包含国庆节Calendar nationalDay = new GregorianCalendar();nationalDay.add(Calendar.MONTH,10);nationalDay.add(Calendar.DATE,1);holidays.setDayExcluded(nationalDay, true);-1:排除该日期scheduler.addCalendar(“ho

    42、lidays“, 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“, “group1“, runDate, null, SimpleTrigger.REPEAT_INDEFINITELY, 60L *

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

    44、添加这两个日期。exclude 为 true 时表示排除指定的日期,如果为 false 时表示包含指定的日期。在定制好 org.quartz.Calendar 后,还需要通过Scheduler#addCalendar(String calName, Calendar calendar, boolean replace, boolean updateTriggers)进行注册,如果 updateTriggers 为true,Scheduler 中已引用 Calendar 的 Trigger 将 得到更新,如所示。在处,我们让一个 Trigger 指定使用 Scheduler 中代表节日的 Cal

    45、endar,这样 Trigger 就会避开五一和国庆这两个特殊日子了。任务调度信息存储在默认情况下 Quartz 将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。比如我们希望安排一个执行 100 次的任务,如果执行到 50 次时系统崩溃了,系统重启时任务的执行计数器将从 0 开始。在大多数实际的应用中,我们往往并不需要保存任务调度的现场数据,因为很少需要规划一个指定执行次数的任务。对于仅执行一次的任务来说,其执行条件信息本身应该是已经持久化的业务数据(如锁定到期解锁任务,解锁的时

    46、间应该是业务数据),当执行完成后,条件信息也会相应改变。当然调度现场信息不仅仅是记录运行次数,还包括调度规则、JobDataMap 中的数据等等。如果确实需要持久化任务调度信息,Quartz 允许你通过调整其属性文件,将这些信息保存到数据库中。使用数据库保存任务调度信息后,即使系统崩溃 后重新启动,任务的调度信息将得到恢复。如前面所说的例子,执行 50 次崩溃后重新运行,计数器将从 51 开始计数。使用了数据库保存信息的任务称为持久化任 务。通过配置文件调整任务调度信息的保存策略其实 Quartz JAR 文件的 org.quartz 包下就包含了一个 quartz.properties 属性

    47、配置文件并提供了默认设置。如果需要调整默认配置,可以在类路 径下建立一个新的 quartz.properties,它将自动被 Quartz 加载并覆盖默认的设置。先来了解一下 Quartz 的默认属性配置文件:代码清单 5 quartz.properties:默认配置集群的配置,这里不使用集群org.quartz.scheduler.instanceName = DefaultQuartzSchedulerorg.quartz.scheduler.rmi.export = falseorg.quartz.scheduler.rmi.proxy = falseorg.quartz.schedul

    48、er.wrapJobExecutionInUserTransaction = false配置调度器的线程池org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount = 10org.quartz.threadPool.threadPriority = 5org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true配置任务调度现场数据保存机制org.quartz.

    49、jobStore.class = org.quartz.simpl.RAMJobStoreQuartz 的属性配置文件主要包括三方面的信息:1)集群信息;2)调度器线程池;3)任务调度现场数据的保存。如果任务数目很大时,可以通过增大线程池的大小得到更好的性能。默认情况下,Quartz 采用 org.quartz.simpl.RAMJobStore 保存任务的现场数据,顾名思义,信息保存在 RAM 内存中,我们可以通过以下设置将任务调度现场数据保存到数据库中:代码清单 6 quartz.properties:使用数据库保存任务调度现场数据org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.tablePrefix = QRTZ_数据表前缀org.quartz.jobStore.dataSource = qzDS数据源名称定义数据源的具体属性org.quartz.dataSource.qzDS.driver = oracle.jdbc.driver.OracleDr

    展开阅读全文
    提示  道客多多所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
    关于本文
    本文标题:Quartz入门教程.doc
    链接地址:https://www.docduoduo.com/p-7232500.html
    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    道客多多用户QQ群:832276834  微博官方号:道客多多官方   知乎号:道客多多

    Copyright© 2025 道客多多 docduoduo.com 网站版权所有世界地图

    经营许可证编号:粤ICP备2021046453号    营业执照商标

    1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png 9.png 10.png



    收起
    展开