以前在框架中使用过,很多都是纯粹的复制粘贴,了解过用法知道如何配置,但时间久了就没什么印象了,现在重新捡起来,再次进行学习。
quartz相关的介绍都已经很多了,我就不重复啰嗦,简单说一下个人的认识和使用。
* 定时任务 quartz的设计比较合理,将调度Scheduler、触发Trigger、任务进行分离Job(这里使用JobDetail创建Job的实例)
* 调度Scheduler负责任务的调度执行以及任务的销毁
* 触发器设定Trigger事件的触发条件或时间,分为SimpleTrigger和CronTrigger两种常用模式,
* 当然还有其他两种模式CalendarIntervalTrigger 按日期触发的Trigger 和 DailyTimeIntervalTrigger 按天触发的Trigger
* 其中CronTrigger中的设置规范基本等同于cron4j,不过增加了秒
* JobDetail是任务的定义,而Job是任务的执行逻辑
在学习cron4j的时候,我使用了的内部类,在创建quartz的时候我也同样使用了内部类,但示例始终不能启动,找了很长时间,没想到这里还有个坑,现在也不知道因为什么。
下面代码是个反面教材,是不能运行的,需要将HelloTask类单独出来写才可以运行。
import java.util.Date; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; import static org.quartz.DateBuilder.evenMinuteDate ; /** * * @author Uboobo * * 定时任务 quartz的设计比较合理,将调度Scheduler、触发Trigger、任务进行分离Job(这里使用JobDetail创建Job的实例) * 调度Scheduler负责任务的调度执行以及任务的销毁 * 触发器设定Trigger事件的触发条件或时间,分为SimpleTrigger和CronTrigger两种常用模式, * 当然还有其他两种模式CalendarIntervalTrigger 按日期触发的Trigger 和 DailyTimeIntervalTrigger 按天触发的Trigger * 其中CronTrigger中的设置规范基本等同于cron4j,增加了秒 * JobDetail是任务的定义,而Job是任务的执行逻辑 * */ public class QuartzTask { // 创建scheduler public static void createScheduler(JobDetail job, Trigger trigger) { try { // 创建scheduler,需要捕获调度异常 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); // 加入这个调度 scheduler.scheduleJob(job, trigger); // 启动之 scheduler.start(); // 运行一段时间后关闭 Thread.sleep(10000); scheduler.shutdown(true); } catch (SchedulerException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 创建Trigger public static Trigger createTrigger() { Trigger trigger = newTrigger() .withIdentity("myTrigger", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(10)//间隔时间是10s .repeatForever()) .build(); return trigger; } // 创建Job public static JobDetail createJob() { JobDetail job = newJob(HelloTask.class) .withIdentity("myJob", "group1") .build(); return job; } // 内部类 ,坑在这这里,需要使用单独的类 static class HelloTask implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDetail detail = context.getJobDetail(); // TODO Auto-generated method stub String name = detail.getJobDataMap().getString("name"); System.out.println(" my job do..." + name); } } public static void main(String[] args) throws Exception { JobDetail job = createJob(); Trigger trigger = createTrigger(); createScheduler(job,trigger); }
代码里没有标注太多注释,这里多说几句,一个quartz任务要执行的话,首先要通过StdSchedulerFactory.getDefaultScheduler() 创建scheduler,只有这样才能使用调度,然后要通过Trigger去创建一个或多个触发器并设定执行时间,然后再去使用JobDetail创建job,再使用job去加载我们要去执行的类,最后使用调度去加载执行。
quartz的设计将其进行分层还是有很多好处,但也增加了一些复杂度,如果直接使用scheduler去调用job也是可以的,但如果实现多重负责设置就比较困难了。
下面贴一下可以运行的代码
public static void main(String [] args) { try { // 创建scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); // 定义一个Trigger Trigger trigger = newTrigger().withIdentity("trigger1", "group1") // 定义name/group .startNow()// 一旦加入scheduler,立即生效 .withSchedule(simpleSchedule() // 使用SimpleTrigger .withIntervalInSeconds(1) // 每隔一秒执行一次 .repeatForever()) // 一直执行,奔腾到老不停歇 .build(); // 定义一个JobDetail JobDetail job = newJob(HelloJob.class) // 定义Job类为HelloQuartz类,这是真正的执行逻辑所在 .withIdentity("job1", "group1") // 定义name/group .usingJobData("name", "quartz") // 定义属性 .build(); // 加入这个调度 scheduler.scheduleJob(job, trigger); // 启动之 scheduler.start(); // 运行一段时间后关闭 Thread.sleep(100000); scheduler.shutdown(true); } catch (Exception e) { e.printStackTrace(); } }
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * hello world Quartz * @author weeks * */ public class HelloJob implements Job { private static Logger _log = LoggerFactory.getLogger(HelloJob.class); /** * Job,Job需要一个公有的构造函数,否则Factory无法构建 */ public HelloJob() { } /** * 实现execute方法 */ public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println(" my job do..."); } }
这里还遗留一个问题,import中使用了 static 有点不太明白,设计者为什么要这么做,这么做有什么好处,待我了解之后再来补充。