1.Quartz是什么
Java中的定时任务调度框架!!!
- Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。
- 在企业级应用中,经常会制定一些“计划任务”,即在某个时间点做某件事情,核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作
- 任务调度涉及多线程并发、线程池维护、运行时间规则解析、运行现场的保护以恢复等方面
- Quartz框架是一个开源的企业级任务调度服务,已经被作为任务调度的良好解决方案
- Quartz对任务调度进行了高度抽象,提出了3个核心概念,并在org.quartz包中通过接口和类进行了描述。
- 任务 JOB:要执行的动作
- 触发器 Trigger: 什么时候被执行
- **调度器 ** :负责绑定触发器和任务 进行任务调度
- 市场上常见的定时任务框架:
- Quartz
- Spring Task
2.Quartz能干什么?
- 场景 #1: 下载交易流水
从银行下载当日交易流水 - 场景 #2: 邮件提醒和告警
公司出于安全考虑,让每个员工三个月换一次邮箱密码。这种情况下,可以创建一个作业(任务),让它每天午夜运行一次,并且向离过期时间不到三天的所有用户发邮件提醒。这里可以恰到好处的用到作业调度器。图 1.1 描绘了密码这个提醒作业。
图 1.1 密码过期的作业每晚发送邮件给密码很快会过期的用户 - 场景 #3: 现在已经把商品加入到购物车了,选中指定的商品开始下单,下单完毕后支付,但是用户没有支付,如果30分钟以内用户不付款,该订单失效!
项目中只要涉及到定时操作或者在指定的时间点要指定某一个任务,就需要使用任务调度框架!!
3.Quartz核心概念
- 任务(JOB):就是执行的工作内容。Quartz提供Job接口来支持任务定义
- 触发器(Trigger)(何时触发的规则):定义触发Job执行的时间触发规则。Quartz提供Trigger类及其子类支持触发器功能
- 调度器(Scheduler):Quartz提供了Scheduler接口,将工作任务和触发器绑定,保证任务可以在正确的时间执行!!
4.Quartz下载
下载:http://www.quartz-scheduler.org/download/index.html
- docs/wikidocs
Quartz 的帮助文件 - docs/api
Quartz 框架的JavaDoc Api 说明文档 - Examples
Quartz 的例子 - Lib
Quartz 使用到的第三方包 - src
源码
5.HelloWorld程序
- 创建maven工程,导入依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
一个最简单的应用包含两个类:
- HelloJob.java
任务类,需要实现 job 接口,里面实现了你想要 定时执行的方法 - SimpleExample.java
主线程,用于任务的调度,执行等操作.
上代码:
- HelloJob.java
public class HelloJob implements Job {
/**
* 实现你自己的定时方法 ,至于里面写什么,您说了蒜!<br>
* 这里只输出 HelloWorld!
*/
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
// 输出 HelloWorld !
System.out.println("Hello World! - " + new Date());
}
}
任务很简单,HelloJob 实现了Quartz 的Job接口中的execute方法,任务的内容就是打印一行字。具体这个任务应该何时去执行,都在SimpleExample.java里面去定义实现。
- SimpleExample.java
public class SimpleExample {
public static void main(String[] args) throws Exception {
// 创建一个任务
JobDetail job = new JobDetailImpl("HelloJob", "group1", HelloJob.class);
// 创建一个触发器
SimpleTrigger simTrig = new SimpleTriggerImpl("trigRemindJob",SimpleTrigger.REPEAT_INDEFINITELY,3000);
// 创建调度者工厂
SchedulerFactory sfc = new StdSchedulerFactory();
// 创建一个调度者
Scheduler sched = sfc.getScheduler();
// 注册并进行调度
sched.scheduleJob(job, simTrig);
// 启动调度
sched.start();
// sleep10s
Thread.sleep(10000);
// 关闭调度
sched.shutdown();
}
}
通过代码可以看到几个重要的类:
- JobDetail: 真正的任务内容,任务本身是集成Job接口的,但是真正的任务是JobBuilder通过反射的方式实例化的,
- Trigger: 触发器,定义任务应当开始的时间,主要分为两类SimpleTrigger,CronTrigger,当前例子的就是简单触发器,CronTrigger主要用于处理quartz表达式定义的任务,比如每个月20号,每个星期一之类的。
- Scheduler: 计划执行者,现在我们有了要做的内容(HelloJob),有了要做的时间(下一分钟),接下来,就把这两个内容填充到计划任务Scheduler对象里面,到了时间它就可以自动运行了.
6.使用CronTrigger
6.1 CronTrigger介绍
CronTrigger也是Trigger的子类
CronTrigger和SimpleTrigger的对比
CronTrigger允许用户更精准地控制任务的运行日期和时间,而不仅仅是定义工作的频度
CronTrigger通过Cron表达式定义准确的运行时间点。
创建CronTrigger的语法如下:
创建CronTrigger的语法很简单,最关键的是Cron表达式的编写
要使用CronTrigger,必须掌握Cron表达式
Cron表达式由6~7个由空格分隔的时间元素组成。第7个元素可选
Cron表达式的每个字段,都可以显式地规定一个值(如49)、一个范围(如1-6)、一个列表(如1,3,5)或者一个通配符(如*)
Cron表达式有几个特殊的字符,说明如下
“ - ”:中划线,表示一个范围 1-10
“ , ”:使用逗号间隔的数据,表示一个列表 1,8,10
“ * ”:表示每一个值,它可以用于所有字段。例如:在小时字段表示每小时 *
“ ? ”:该字符仅用于“月份中的哪一天”字段和“星期几”字段,表示不指定值
“ / ”:通常表示为x/y,x为起始值,y表示值的增量。
“ L ”:表示最后一天,仅在日期和星期字段中使用
“ # ”:只能用于“星期几”字段,表示这个月的第几个周几。例如:“6#3”指这个月第三个周五
6.2 Cron表达式示例
语法格式:
秒 分 时 天 月 星期 年
常用表达式例子
(1)0 0 2 1 * ? * 表示在每月的1日的凌晨2点调整任务
(2)0 15 10 ? * MON-FRI 表示周一到周五每天上午10:15执行作业
(3)0 15 10 ? 6L 2002-2006 表示2002-2006年的每个月的最后一个星期五上午10:15执行作
(4)0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
(5)0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
(6)0 0 12 ? * WED 表示每个星期三中午12点
(7)0 0 12 * * ? 每天中午12点触发
(8)0 15 10 ? * * 每天上午10:15触发
(9)0 15 10 * * ? 每天上午10:15触发
(10)0 15 10 * * ? * 每天上午10:15触发
(11)0 15 10 * * ? 2005 2005年的每天上午10:15触发
(12)0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
(13)0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
(14)0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
(15)0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
(16)0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
(17)0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
(18)0 15 10 15 * ? 每月15日上午10:15触发
(19)0 15 10 L * ? 每月最后一日的上午10:15触发
(20)0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
(21)0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
(22)0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发
Cron表达式在线插件:http://cron.qqe2.com/
6.3 Cron表达式案例
public static void main(String[] args) throws SchedulerException, InterruptedException, ParseException {
// 创建一个任务
JobDetail job = new JobDetailImpl("HelloJob", "group1", HelloJob.class);
// 创建Cron触发器
CronTrigger cronTrig = new CronTriggerImpl("HelloJob", "group1", "1/3 * * * * ?");
// 创建调度者工厂
SchedulerFactory sfc = new StdSchedulerFactory();
// 创建一个调度者
Scheduler sched = sfc.getScheduler();
// 注册并进行调度
sched.scheduleJob(job, cronTrig);
// 启动调度
sched.start();
// sleep10s
Thread.sleep(10000);
// 关闭调度
sched.shutdown();
}