Quartz[kwɔːts]:石英,其框架和名字同样简单朴素又不失魅力,在Java程序界,Quartz大名鼎鼎,不少Java应用几乎都集成或构建了一个定时任务调度系统,Quartz是一个定时任务调度框架(Quartz官网:http://www.quartz-scheduler.org/)。这个工具java
在美团中的有大量使用,详见他们的官方博客:http://tech.meituan.com/ 。Quartz是一个很轻量级的java库,几乎包含了全部定时的功能。主要接口是Schedule,提供了一些简单的操做:安排任务或取消任务,启动或者中止任务。若是你想在应用中使用Quartz,spring
应该实现Job接口,包含了一个execute()方法。若是你想在一个任务执行时间到了的时候通知你,组件应该实现TriggerListener 或者JobListener 接口。Quartz任务能够在你的应用中启动和执行,能够做为一个独立的应用程序(经过RMI接口[即Remote Method微信
Invoke 远程方法调用]),也但是在一个J2EE应用中执行。mybatis
1. 何为定时任务调度框架?多线程
简而言之,它能够领会咱们的意图在将来某个时刻作咱们想要作的事情,好比,每个月月末的财务报表给财务部门,定时给领导发个邮件短信等等。这时候咱们就须要用到任务调度框架Quartz了。其不只简单易使用,而且能够与spring集成(这才是重点哦!就目前而并发
言,一个Java项目其基础框架不外乎SSH(struts2+spring+hibernate)、SSM(springMVC+spring+mybatis)。固然,也有一些团队喜欢springMVC+spring+hibernate这样搭建。不过,不管是那种搭配spring几乎是不可或缺的)。任务调度自己涉及到多线程框架
并发、运行时间规则制定和解析、场景保持与恢复、线程池维护等诸多方面的工做。若是直接使用自定义线程这种刀耕火种的原始办法,开发任务调度程序是一项颇具挑战性的工做。Java开源的好处就是:领域问题都能找到现成的解决方案(因此圈里也流行这么一句:工具
天上飞的理念,必有落地的产品)。 学习
但任务调度除以时间为关注点外,还应考虑资源的分配。大多数系统都要对资源使用进行控制:服务线程的最大数目必须限额;考虑使用线程池以便共享服务的线程资源、下降频繁建立、销毁线程的消耗。spa
2. Quartz是什么?
Quartz是一个任务调度框架(库),它几乎能够集成到任何应用系统中。术语”job schedule”彷佛为不一样的人提供了不一样的想法。总之,做业调度是负责执行(或通知)其余软件组件在预约时间执行的服务组件。虽然经过schedule能够简单实现一些系统任务定时执
行,当您学习如何使用它来驱动应用程序的业务流程的流程时,Quartz的所有潜力是能够实现的。
3. Quartz的一些特色
1)很是灵活的,并包含多个使用范例,它们能够单独或一块儿使用,以实现您所指望的行为,并使您可以以最“天然”的方式来编写您的项目的代码。
2)很是轻量级的,只须要很是少的配置 —— 它实际上能够被跳出框架来使用,若是你的需求是一些相对基本的简单的需求的话。
3)具备容错机制,而且能够在重启服务的时候持久化你的定时任务,你的任务也不会丢失。
4)不是一个任务队列——虽然它确实能够在一些小规模应用中合理的做为一个任务队列来使用。
5)不是一个网格计算引擎——虽然在某些小规模应用中,这样作确实能够达到应用的要求(定时计算、统计一些数据)。
6)不是一个提供给业务人员的执行服务——它是一个库,很容易集成到应用程序中去作一些将来某时刻可能会一直循环执行的相关的任务。
4. 综观目前的 Web 应用,多数应用都具有任务调度的功能。几种任务调度的 Java 实现方法,包括 Timer,Scheduler, Quartz 以及 JCron Tab等等,其优缺点进行比较,本文不作重点介绍。若有兴趣能够参考如下文章(Spring提供的三种定时任务机制及其比
较 :http://blog.csdn.net/52rainbow/article/details/4004206 ;Flux scheduler:https://flux.ly/ ;三种定时任务的比较:http://blog.csdn.net/liu1pan2min3/article/details/51540470)
5. Quartz 基础结构
Quartz 对任务调度的领域问题进行了高度抽象,提出了调度器、任务和触发器 3 个核心概念,并在 org.quartz 中经过接口和类对核心概念进行描述。
Job:接口。开发者经过实现该接口定义须要执行的任务。
JobDetail:Quartz 在每次执行 Job 时,都从新建立一个 Job 实例,因此它不是直接接受一个 Job 的实例,而是接受一个 Job 实现类,以便运行时经过反射机制实例化 Job。所以须要一个类来描述 Job 的实现类及其余相关的静态信息,如 Job 名称、描述、关联
的监听器等,JobDetail 承担了这一角色。
Trigger:描述触发 Job 执行的时间触发规则。主要有 SimpleTrigger、CronTrigger 两个实现类。
SimpleTrigger:当仅须要触发一次或者以固定间隔周期执行时。
CronTrigger:能够经过 Cron 表达式定义出各类复杂的调度方案。
Calendar:一些日历特定时间点的集合(能够简单的理解为 java.util.Calendar 的集合:java.util.Calendar )。一个 Trigger 能够和多个 Calendar 关联,以便包含或排除某些时间点。
Scheduler:一个 Quartz 的独立运行容器,Trigger 和 JobDetail 能够注册到 Scheduler 中,二者在 Scheduler 中拥有各自的组及名称。组及名称是 Scheduler 查找容器中某一对象的依据,Trigger 和 JobDetail 的组及名称的组合都必须惟一(但 Scheduler
和 Trigger 的组合名称能够相同,由于他们是不一样的类型,处于不一样的容器中)。Scheduler 能够将 Trigger 绑定到某一个 JobDetails 中,这样当 Trigger 被触发时,对应的 Job 就被执行。一个 Job 能够对应多个 Trigger,但一个 Trigger 只能对应一个 Job。
6. 使用 SimpleTrigger
步骤:
实现 Job 接口,可以使 Java 类变为可调度的任务;
建立描述 Job 的 JobDetail 对象;
建立 SimpleTrigger 对象;
设置触发 Job 执行的时间规则;
经过 SchedulerFactory 获取 Scheduler 对象;
向 SchedulerFactory 中注册 JobDetail 和 Trigger;
启动调度任务。
7. 使用 CronTrigger
CronTriggr 可以提供比 SimpleTrigger 更有具体实际意义的调度方案,调度规则基于 Cron 表达式,CronTrigger 支持日历相关的重复时间间隔(例如:每个月第一个周一执行),而不是简单的周期时间间隔。
8. Cron 表达式
Quartz 使用相似于 Linux 下的 Cron 表达式定义时间规则,Cron 表达式由 6 或 7 个空格分隔的时间字段组成。
Cron 表达式对特殊字符的大小写不敏感.
9. Cron 表达式中的特殊字符
*:可用于全部字段,表示对应时间域的每个时刻。例如:* 在分钟字段时,表示 每分钟
?:只能用在日期和星期字段中,表示一个毫无心义的值,至关于占位符
-:表示一个范围。例如:在小时字段中使用 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 用在日期字段中,表明这个月的最后一天
L 用在星期字段中,表明星期六
若 L 出如今星期字段里,且前面有一个数值 X,则表示 这个月的最后星期 X,例如 6L 表示该月的最后一个星期五
W:该字符只能出如今日期字段里,是对前导日期的修饰,表示离该日期最近的工做日。例如:15W 表示离该月 15 号最近的工做日:若 15 号是星期六,则匹配 14 号;若 15 号是星期日,则匹配 16 号;若 15 号是星期二,则匹配 15 号。
注意1:关联的匹配日期不能跨月。例如用户指定 1W,若 1 号是星期六,则匹配 3 号。
注意2:W 字符串只能指定单一日期,而不能指定日期范围。
LW:在日期字段能够组合使用 LW,意为当月的最后一个工做日
#:只能在星期字段中使用,表示当月某个工做日。例如:6#3 表示当月的第三个星期五(6表示星期五,#3表示当月的第三个),4#5 表示当月的第五个星期三,若没有第五个星期三,则忽略不触发
C:该字符只在日期和星期字段中使用,表明 Calendar。意为计划所关联的日期,若是日期没有被关联,则至关于日历中全部日期。例如:5C 在日期字段中就至关于 5 日之后的第一天。1C 在星期字段中至关于星期往后的第一天。
10. Cron 表达式示例
0 0 12 * * ?:天天中午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期间的每1分钟触发
0 0/5 14 * * ?:在天天下午2点到下午2:55期间的每5分钟触发
0 0/5 14, 18 * * ?:在天天下午2点到2:55期间和下午6点到6:55期间的每5分钟,触发
0 0-5 14 * * ?:在天天下午2点到下午2:05期间的每1分钟触发
0 10,44 14 ? 3 WED:每一年三月的星期三的下午2:10和2: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 2002-2005:2002年至2005年的每个月的最后一个星期五上午10:15触发
0 15 10 ? * 6#3:每个月的第三个星期五上午10:15触发
11. 在 Spring 中使用 Quartz
Spring 进一步下降了使用 Quartz 的难度:
为建立 Quartz 的 Scheduler、Trigger 和 JobDetail 提供了便利的 FactoryBean 类,以便可以在 Spring 容器中享受注入.
在 Spring 中配置 JobDetail :
Spring 提供了一个 MethodInvokingJobDetailFactoryBean, 经过这个 FactoryBean 能够将 Spring 容器中 Bean 的方法包装成 Quartz 任务,这样就没必要为 Job 建立对应的类了.
12. 在 Spring 中配置 CronTrigger
Spring 为 CronTrigger 提供了更具 Bean 风格的 CronTriggerFactoryBean.
13. 在 Spring 中配置 Secheduler
Spring 提供了 SchedulerFactoryBean,这个 Bean 拥有以下功能:
以更具备 Bean 风格的方式为 Scheduler 提供配置信息。
让 Scheduler 和 Spring IOC 容器的生命周期创建关联:IOC 容器启动后,Secheduler 开始工做,IOC 容器关闭前,自动关闭 Scheduler。
startupDelay 属性:在 SchedulerFactoryBean 初始化完成后,延迟多少秒启动 Scheduler,默认为 0,即当即启动。通常状况下,能够经过设置该属性使 Scheduler 延迟一小段时间后启动,以便让 Spring 可以更快初始化容器中的其它 Bean。
quartzPorperties属性:类型为 Properties,容许在 Spring 中定义 Quartz 的属性。其值将覆盖 quartz.properties 配置文件中的配置。
<!-- Start -->
本文只是Quartz的一个入门,接下来我会逐步推出Quartz的高级用法和在实际项目中的Demo。获知及时信息,请关注个人我的微信订阅号:0与1的那点事
<!-- End -->
本文为博主原创文章,转载请注明出处!
http://www.cnblogs.com/libingbin/
感谢您的阅读。