1 写在前面
最近公司的业务需要用到定时任务,框架选型用的是 Quartz ,这里作学习记录。
2 Quartz 主要成员
Quartz 的核心由三大接口组成,分别是 Job,Trigger,Scheduler
2.1 Job
描述执行具体的任务,其结构与 Runnable 类似,只有一个 void 类型的方法 execute(JobExecutionContext context),它还有一个子类 InterruptableJob,表示一个可终止的任务
2.1.1 InterruptableJob
在 Job 的基础只添加了一个 void 类型的方法 interrupt() ,用于终止任务,它的调用发生在在 QuartzScheduler#shutdown(boolean) 中,这要求我们需要像编写一个可终止的的 Runnable 一样编写 execute 方法。
2.2 Trigger
用来描述一个 Job 的 execute 方法何时执行
2.3 Scheduler
类似队列与线程池,存放各种 Job 的信息与 Trigger ,管理任务的添加,移除,替换,运行等
3 Quartz 的初步使用
Scheduler:作为一个管理任务的容器,Scheduler 应该有类似线程池的提交任务与关闭池的方法:对应的添加任务方法分别为 addJob, scheduleJob,很不巧这些方法的签名是 JobDetail;
JobDetail:JobDetail 有一个实现类 JobDetailImpl ,并且空构造器表示必须指定 name,class,group。class 是指 Job 接口的实现;group 是可选的,默认使用 default;
Trigger:Trigger 有多个实现类,这里只涉及到基本实现 SimpleTriggerImpl;
上述的三个接口都有对应的建造类或者工厂类。
3.1 一个普通的定时任务
1 /** 2 * @author pancc 3 * @version 1.0 4 */ 5 public class SimpleJobDemo { 6 public static void main(String[] args) throws SchedulerException, InterruptedException { 7 JobDetail detail = JobBuilder.newJob(SimpleJob.class) 8 .withIdentity("simple", "group0") 9 .build(); 10 11 Trigger trigger = TriggerBuilder.newTrigger() 12 .withIdentity("simple_trigger") 13 .startNow() 14 .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(2)) 15 .build(); 16 17 Scheduler scheduler = new StdSchedulerFactory().getScheduler(); 18 19 scheduler.start(); 20 scheduler.scheduleJob(detail, trigger); 21 /* 22 * 10 秒钟后关闭 23 */ 24 Thread.sleep(10_000); 25 scheduler.shutdown(); 26 } 27 28 public static class SimpleJob implements Job { 29 @Override 30 public void execute(JobExecutionContext context) { 31 System.out.printf("now date: %s", new Date()); 32 } 33 } 34 35 }
上边的代码创建了一个任务打印当前任务,并且指定它的运行开始时间为提交的时候,并且周期为2秒,持续永久。10 秒钟后关闭容器。
4 任务创建中的坑
必要的属性:JobDetail 必须有描述名,组在未设定时使用 default。
可访问性:在一般的代码中,我们习惯性限制类的访问,比如上边的 SimpleJob 我们可能会定义 private(意味着它的构造器也是 private 的),这在 Quartz 中是不被允许的。Job 的空构造器必须是 pubilc 的,这与后续 Quartz 的特性有关。