quartz简介
Quartz的概念并不是很复杂,简单说就是一个java的定时调度器,我们只需要搞明白几个概念,然后知道如何去开启和关闭一个定时任务
- Job
表示一个工作,要执行的具体内容。此接口中只有一个方法 void execute(JobExecutionContext context)我们要去重写这个方法,来放置自己的任务逻辑。
- JobDetail
JobDetail表示一个具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略。
- Trigger
代表一个调度参数的配置,什么时候去调
- Scheduler
代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了
- Calendar
它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合。一个Trigger可以和多个Calendar关联, 以便排除或包含某些时间点。
- ThreadPool
Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。
下图描述了Scheduler的内部组件结构,SchedulerContext提供Scheduler全局可见的上下文信息,每一个任务都对应一个JobDataMap,虚线表达的JobDataMap表示对应有状态的任务:
quartz简单例子
1.引入maven
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
2.创建job任务
package com.chenfan.service;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Job;
import java.util.Date;
public class HelloQuartzJob implements Job{
public void execute(JobExecutionContext context)
throws JobExecutionException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
System.out.println("Hello, Quartz! - executing its JOB at "+ dateFormat.format(new Date()) + " by " + context.getTrigger().getCalendarName());
}
}
3.调度任务
import java.sql.Date;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
public class HelloQuartzScheduling {
public static void main(String[] args)throws SchedulerException {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler(); //创建scheduler容器
JobDetail jobDetail = new JobDetail("helloQuartzJob",
Scheduler.DEFAULT_GROUP, HelloQuartzJob.class); // 加载可执行调度程序
SimpleTrigger simpleTrigger = new SimpleTrigger("simpleTrigger",
Scheduler.DEFAULT_GROUP); // 加载触发器,这里是简单触发器
simpleTrigger.setStartTime(new Date(System.currentTimeMillis()));
simpleTrigger.setRepeatInterval(5000); // 5s执行一次
simpleTrigger.setRepeatCount(10); // 重复执行10次
scheduler.scheduleJob(jobDetail, simpleTrigger);
scheduler.start();
}
}
4.执行结果
Trigger触发器
Quartz有两大触发器,除了上面使用的SimpleTrigger外,就是CronTrigger。CronTrigger能够提供复杂的触发器表达式的支持。CronTrigger是基于Unix Cron守护进程,它是一个调度程序,支持简单而强大的触发器语法。
使用CronTrigger主要的是要掌握Cron表达式。Cron表达式包含6个必要组件和一个可选组件,如下表所示。
特殊字符含义见下表
Cron表达式举例
“30 * * * * ?” 每半分钟触发任务
“30 10 * * * ?” 每小时的10分30秒触发任务
“30 10 1 * * ?” 每天1点10分30秒触发任务
“30 10 1 20 * ?” 每月20号1点10分30秒触发任务
“30 10 1 20 10 ? * “ 每年10月20号1点10分30秒触发任务
“30 10 1 20 10 ? 2011” 2011年10月20号1点10分30秒触发任务
“30 10 1 ? 10 * 2011” 2011年10月每天1点10分30秒触发任务
“30 10 1 ? 10 SUN 2011” 2011年10月每周日1点10分30秒触发任务
“15,30,45 * * * * ?” 每15秒,30秒,45秒时触发任务
“15-45 * * * * ?” 15到45秒内,每秒都触发任务
“15/5 * * * * ?” 每分钟的每15秒开始触发,每隔5秒触发一次
“15-30/5 * * * * ?” 每分钟的15秒到30秒之间开始触发,每隔5秒触发一次
“0 0/3 * * * ?” 每小时的第0分0秒开始,每三分钟触发一次
“0 15 10 ? * MON-FRI” 星期一到星期五的10点15分0秒触发任务
“0 15 10 L * ?” 每个月最后一天的10点15分0秒触发任务
“0 15 10 LW * ?” 每个月最后一个工作日的10点15分0秒触发任务
“0 15 10 ? * 5L” 每个月最后一个星期四的10点15分0秒触发任务
“0 15 10 ? * 5#3” 每个月第三周的星期四的10点15分0秒触发任务
将上面HelloQuartz例子中SimpleTrigger换成CronTrigger,代码如下。
public class HelloQuartzScheduling {
public static void main(String[] args) throws SchedulerException, ParseException {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
JobDetail jobDetail = new JobDetail("helloQuartzJob",
Scheduler.DEFAULT_GROUP, HelloQuartzJob.class);
String cronExpression = "30/4 * * * * ? 2017";
CronTrigger cronTrigger = new CronTrigger("cronTrigger",
Scheduler.DEFAULT_GROUP, cronExpression);
scheduler.scheduleJob(jobDetail, cronTrigger);
scheduler.start();
//scheduler.shutdown(true);
}
}
排除一段时间
使用Calender可以排除一些不需要定时的日期
-
CronCalendar:使用表达式排除某些时间段不执行
-
DailyCalendar:指定的时间范围内的每一天不执行
-
HolidayCalendar:排除节假日
-
MonthlyCalendar:排除月份中的数天
-
WeeklyCalendar:排除星期中的一天或多天
例子:
public class HelloQuartzScheduling {
public static void main(String[] args)
throws SchedulerException, ParseException {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
JobDetail jobDetail = new JobDetail("helloQuartzJob",
Scheduler.DEFAULT_GROUP, HelloQuartzJob.class);
Calendar cal = Calendar.getInstance();
cal.set(2017, Calendar.OCTOBER, 1); // 国庆节
HolidayCalendar holidayCal = new HolidayCalendar();
holidayCal.addExcludedDate(cal.getTime()); // 排除该日期
// addCalendar(String calName, Calendar calendar,
// boolean replace, boolean updateTriggers)
scheduler.addCalendar("calendar", holidayCal, true, false);
String cronExpression = "30/5 * * * * ?"; // 每5s触发任务
CronTrigger cronTrigger = new CronTrigger("cronTrigger",
Scheduler.DEFAULT_GROUP, cronExpression);
cronTrigger.setCalendarName("calendar");
scheduler.scheduleJob(jobDetail, cronTrigger);
scheduler.start();
}
}
JobStore: 任务持久化
Quartz支持任务持久化,这可以让你在运行时增加任务或者对现存的任务进行修改,并为后续任务的执行持久化这些变更和增加的部分。中心概念是JobStore接口。默认的是RAMJobStore,它的优点是速度。因为所有的 Scheduler 信息都保存在计算机内存中,访问这些数据随着电脑而变快。而无须访问数据库或IO等操作,但它的缺点是将 Job 和 Trigger 信息存储在内存中的。因而我们每次重启程序,Scheduler 的状态,包括 Job 和 Trigger 信息都丢失了