任务调度
在企业级应用中,经常会制定一些“计划任务”,即在某个时间点做某件事情 核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作 任务调度涉及多线程并发、线程池维护、运行时间规则解析、运行现场的保护以恢复等方面 Quartz框架是一个开源的企业级任务调度服务,已经被作为任务调度的良好解决方案.
Quartz框架核心
Quartz对任务调度进行了高度抽象,提出了3个核心概念,并在org.quartz包中通过接口和类进行了描述
任务:就是执行的工作内容。Quartz提供Job接口来支持任务定义
触发器:定义触发Job执行的时间触发规则。Quartz提供Trigger类及其子类支持触发器功能
调度器:Quartz提供了Scheduler接口,将工作任务和触发器绑定,保证任务可以在正确的时间执行
运行环境
任务调度
任务执行
任务持久化
事务
集群
监听器和插进
Quartz案例
1.找到Quartz框架的jar包
2.开始创建entity实体层定义任务的模板
package cn.entity;public class Plan { //时间 private String date; //任务 private String task; public Plan() { super(); } public Plan(String date, String task) { super(); this.date = date; this.task = task; } @Override public String toString() { return "Plan [date=" + date + ", task=" + task + "]"; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getTask() { return task; } public void setTask(String task) { this.task = task; } }
3.定制一个泛型集合用户存储多个Plan对象,提供一个方法读取该泛型集合中的data
package cn.service;import java.util.ArrayList;import java.util.List;import cn.entity.Plan;/** * 提醒服务类 * @author * */public class RemindService { //01.创建一个集合,并且方法返回值是一个集合类型 public ListgetPlansForToday(){ List list=new ArrayList (); Plan plan1=new Plan("2016年12月16日","2016最后一个月"); Plan plan2=new Plan("2016年12月18日","Quartz"); list.add(plan1); list.add(plan2); return list; } //02.用来打印集合中提醒内容的方法 public void printMessage(){ List list = getPlansForToday(); for (Plan plan : list) { //单个的plan System.out.println("计划的时间"+plan.getDate()+"\t计划内容"+plan.getTask()); } }}
4.提醒业务类
package cn.quartz;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import cn.service.RemindService;/** * 提醒业务 * @author * *///让一个普通类变成计划public class RemindJob implements Job { //植入service 对象 private RemindService service=new RemindService(); @Override public void execute(JobExecutionContext context) throws JobExecutionException { service.printMessage(); } public RemindService getService() { return service; } public void setService(RemindService service) { this.service = service; } }
Job接口中只有一个 execute()方法,在实现类中 实现该方法以执行具体任务。
5.真正的任务对象和触发器对象
package cn.test;import java.util.Date;import org.quartz.CronScheduleBuilder;import org.quartz.CronTrigger;import org.quartz.DateBuilder;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SchedulerFactory;import org.quartz.SimpleScheduleBuilder;import org.quartz.Trigger;import org.quartz.TriggerBuilder;import org.quartz.TriggerKey;import org.quartz.impl.StdSchedulerFactory;import cn.quartz.RemindJob;public class MyQuartzTest { public static void tool() throws SchedulerException, InterruptedException{ //第一步构建Job JobDetail job = JobBuilder.newJob(RemindJob.class)// .withIdentity("job1", "group1")// .build(); //第二步创建Trigger //第一种方式 控制不太好 /* Date runTime = DateBuilder.evenMinuteDate(new Date(System.currentTimeMillis())); Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")// .startAt(runTime).build();*/ //第二种方式 不太好 /*Trigger trigger = TriggerBuilder.newTrigger() .withIdentity(TriggerKey.triggerKey("myTrigger", "myTriggerGroup")) .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(2) .repeatForever()) .startAt(new Date(System.currentTimeMillis()+2000)) .build();*/ //第三步绑定 JOb和Trigger // First we must get a reference to a scheduler //创建调度者工厂 SchedulerFactory sf = new StdSchedulerFactory(); //创建一个调度者 Scheduler sched = sf.getScheduler(); //注册并进行调度 sched.scheduleJob(job, trigger); //启动调度 sched.start(); /*Thread.sleep(3000); * //关闭调度 sched.shutdown();*/ } public static void main(String[] args) throws SchedulerException, InterruptedException { tool(); System.out.println("呵呵"); }}
第一种方式:
第二种方式:
6.使用CronTrigger
CronTrigger也是Trigger的子类
CronTrigger和SimpleTrigger的对比
CronTrigger允许用户更精准地控制任务的运行日期和时间,而不仅仅是定义工作的频度
CronTrigger通过Cron表达式定义准确的运行时间点。创建CronTrigger的语法如下:
7.Cron表达式
要使用CronTrigger,必须掌握Cron表达式
Cron表达式由6~7个由空格分隔的时间元素组成。第7个元素可选
Cron表达式的每个字段,都可以显式地规定一个值(如49)、一个范围(如1-6)、一个列表(如1,3,5)或者一个通配符(如*)
8.Cron表达式有几个特殊的字符,说明如下
“ - ”:中划线,表示一个范围
“ , ”:使用逗号间隔的数据,表示一个列表
“ * ”:表示每一个值,它可以用于所有字段。例如:在小时字段表示每小时
“ ? ”:该字符仅用于“月份中的哪一天”字段和“星期几”字段,表示不指定值
“ / ”:通常表示为x/y,x为起始值,y表示值的增量。
“ L ”:表示最后一天,仅在日期和星期字段中使用
“ # ”:只能用于“星期几”字段,表示这个月的第几个周几。例如:“6#3”指这个月第三个周五
9.Cron表达式案例
测试:
package cn.test;import java.util.Date;import org.quartz.CronScheduleBuilder;import org.quartz.CronTrigger;import org.quartz.DateBuilder;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SchedulerFactory;import org.quartz.SimpleScheduleBuilder;import org.quartz.Trigger;import org.quartz.TriggerBuilder;import org.quartz.TriggerKey;import org.quartz.impl.StdSchedulerFactory;import cn.quartz.RemindJob;public class MyQuartzTest { public static void tool() throws SchedulerException, InterruptedException{ //第一步构建Job JobDetail job = JobBuilder.newJob(RemindJob.class)// .withIdentity("job1", "group1")// .build(); //第二步创建Trigger /** * 2016年每月的第三个星期六上午10:18触发 0 18 10 ? * 6#3 2016 */ CronTrigger trigger=TriggerBuilder.newTrigger()// .withIdentity("myTrigger", "myTriggerGroup")// .withSchedule(CronScheduleBuilder.// cronSchedule("0 18 10 ? * 6#3 2016")).build(); //第三步绑定 JOb和Trigger // First we must get a reference to a scheduler //创建调度者工厂 SchedulerFactory sf = new StdSchedulerFactory(); //创建一个调度者 Scheduler sched = sf.getScheduler(); //注册并进行调度 sched.scheduleJob(job, trigger); //启动调度 sched.start(); } public static void main(String[] args) throws SchedulerException, InterruptedException { tool(); System.out.println("呵呵"); }}