MyJob.java:定义任务(需要是public)
QuartzTest.java:主线程,用于调用任务。
这个例子的目的是在当前运行时间的下一个整数分钟输出一行文字
MyJob:
可以看到,任务很简单,MyJob 实现了Quartz的Job接口中的execute方法,任务的内容就是打印一行字。具体这个任务应该何时去执行,都在QuartzTest里面去定义实现。
QuartzTest:
通过代码可以看到几个重要的类:
QuartzTest.java:主线程,用于调用任务。
这个例子的目的是在当前运行时间的下一个整数分钟输出一行文字
MyJob:
- public class MyJob implements Job {
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- System.out.println("任务正在执行,执行时间: " + Calendar.getInstance().getTime());
- }
- }
可以看到,任务很简单,MyJob 实现了Quartz的Job接口中的execute方法,任务的内容就是打印一行字。具体这个任务应该何时去执行,都在QuartzTest里面去定义实现。
QuartzTest:
- public static void main(String[] args) throws Throwable {
- SchedulerFactory factory = new StdSchedulerFactory();
- // 从工厂里面拿到一个scheduler实例
- Scheduler scheduler = factory.getScheduler();
- // 计算任务的开始时间,DateBuilder.evenMinuteDate方法是取下一个整数分钟
- Date runTime = DateBuilder.evenMinuteDate(new Date());
- // 真正执行的任务并不是Job接口的实例,而是用反射的方式实例化的一个JobDetail实例
- JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build();
- // 定义一个触发器,startAt方法定义了任务应当开始的时间
- Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();
- // 将任务和Trigger放入scheduler
- scheduler.scheduleJob(job, trigger);
- scheduler.start();
- try {
- // 等待65秒,保证下一个整数分钟出现,这里注意,如果主线程停止,任务是不会执行的
- Thread.sleep(65L * 1000L);
- } catch (Exception e) {
- }
- // scheduler结束
- scheduler.shutdown(true);
- }
通过代码可以看到几个重要的类:
- JobDetail: 真正的任务内容,任务本身是集成Job接口的,但是真正的任务是JobBuilder通过反射的方式实例化的,
- Trigger: 触发器,定义任务应当开始的时间,主要分为两类SimpleTrigger,CronTrigger,当前例子的就是简单触发器,CronTrigger主要用于处理quartz表达式定义的任务,比如每个月20号,每个星期一之类的。
- Scheduler: 计划表(可能翻译的不太贴切),现在我们有了要做的内容,有了要做的时间,接下来,就把这两个内容填充到计划任务Scheduler对象里面,到了时间它就可以自动运行了。
顺大便回顾一下Quartz的基本使用方法,联系windows自带的计划任务,假想场景如下:
下面先对MyJob做个小改动,让我们定义的任务Key打印出来。
接下来这个小例子是QuartzMultiJobTest.java,是个多任务例子,比如说,我想让我的任务五秒钟后执行,并且开始执行之后,隔三秒钟再执行一次,再隔三秒钟再执行一次,实现如下,注意@NOTICE标记:
主要需要理解的是
1.DateBuilder.nextGivenSecondDate这个方法的执行时间
2.同一个任务可以多次注册
3.重复执行需要在Trigger的设置里面加入SimpleScheduleBuilder,设置重复次数和重复时间即可。repeatForever()方法永远表示一直重复执行。
4.有三个API用法没放到例子中:
a.scheduler.addJob(job, true); //无trigger注册,表示任务立即执行。
b.scheduler.rescheduleJob(trigger.getKey(), trigger); //在scheduler.start之后调用,可以在job开始后重新定义trigger,然后重新注册。
c.scheduler.getMetaData().getNumberOfJobsExecuted() 可以在shutdown后取出执行的任务数量,一些基本信息封装在SchedulerMetaData对象中。
- 1.我要让电脑查杀病毒(对应Quartz: 实现Job接口的execute方法,后期通过反射实例化JobDetail对象)。
- 2.我想让电脑在五分钟之后做查杀病毒这个job(对应Quartz:通过TriggerBuilder来new出一个时间为五分钟之后的Trigger)。
- 3.把上面我想象到的时间:五分钟之后;任务:查杀病毒 放到windows的定时任务当中,点击确定(对应Quartz:通过SchedulerFactory拿到Scheduler实例,将JobDetail与Trigger通过scheduleJob方法注册到Scheduler中,再调用start方法就可以了)。
下面先对MyJob做个小改动,让我们定义的任务Key打印出来。
- public class MyJob implements Job {
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- // @NOTICE JobExecutionContext 是任务执行的上下文,可以拿到任务的Key
- String jobName = context.getJobDetail().getKey().getName();
- System.out.println("任务Key:" + jobName + " 正在执行,执行时间: " + Calendar.getInstance().getTime());
- }
- }
接下来这个小例子是QuartzMultiJobTest.java,是个多任务例子,比如说,我想让我的任务五秒钟后执行,并且开始执行之后,隔三秒钟再执行一次,再隔三秒钟再执行一次,实现如下,注意@NOTICE标记:
- public class QuartzMultiJobTest {
- public static void main(String[] args) throws Throwable {
- SchedulerFactory factory = new StdSchedulerFactory();
- Scheduler scheduler = factory.getScheduler();
- // @NOTICE 任务的开始时间,nextGivenSecondDate方法表示:当前时间之后,每当秒数是13的倍数都是触发时间,当然只触发一次
- // 比如:00:00:12秒开始主线程,则13秒就会触发任务,如果00:00:14秒开始主线程,则在26秒触发任务
- Date runTime = DateBuilder.nextGivenSecondDate(null, 13);
- JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build();
- Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();
- scheduler.scheduleJob(job, trigger);
- // @NOTICE 将同一个Job实现作为另外一个任务注册到scheduler,注意名字要区分
- job = JobBuilder.newJob(MyJob.class).withIdentity("job2", "group1").build();
- trigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group1").startAt(runTime).build();
- scheduler.scheduleJob(job, trigger);
- // @NOTICE 重复执行,job3表示第一次执行完之后,每隔3秒钟执行一次,重复5次,withRepeatCount参数不包括第一次执行那次,即job3总共执行6次
- job = JobBuilder.newJob(MyJob.class).withIdentity("job3", "group1").build();
- trigger = TriggerBuilder.newTrigger().withIdentity("trigger3", "group1")
- .withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(5).withIntervalInSeconds(3)).startAt(runTime).build();
- scheduler.scheduleJob(job, trigger);
- scheduler.start();
- try {
- // 等待20秒
- Thread.sleep(20L * 1000L);
- } catch (Exception e) {
- }
- scheduler.shutdown(true);
- }
- }
主要需要理解的是
1.DateBuilder.nextGivenSecondDate这个方法的执行时间
2.同一个任务可以多次注册
3.重复执行需要在Trigger的设置里面加入SimpleScheduleBuilder,设置重复次数和重复时间即可。repeatForever()方法永远表示一直重复执行。
4.有三个API用法没放到例子中:
a.scheduler.addJob(job, true); //无trigger注册,表示任务立即执行。
b.scheduler.rescheduleJob(trigger.getKey(), trigger); //在scheduler.start之后调用,可以在job开始后重新定义trigger,然后重新注册。
c.scheduler.getMetaData().getNumberOfJobsExecuted() 可以在shutdown后取出执行的任务数量,一些基本信息封装在SchedulerMetaData对象中。
前面讲的都是简单触发器,直接传入一个时间让任务执行,这一话讲CronTrigger的例子。
CronTrigger也是Quartz最重要的特色之一,通过Quartz特有的Cron表达式来确定某类时间,能完成类似"每个月二十号XXX,每个星期三XXX"之类的任务。
先对MyJob做个小的修改,时间用中文来输出,不然看起来太费劲,逻辑上没有任何修改。
接下来创建QuartzCronTest.java,这里采用了CronTrigger作为触发器,注意NOTICE注释下面的代码:
其实使用起来很简单,把Trigger的传入“升级”为CronTrigger就可以了,通过CronScheduleBuilder把"0 0 12 * * ?"这样的Cron表达式传入CronTrigger当中,任务就可以在指定的时间自动执行啦。
CronTrigger也是Quartz最重要的特色之一,通过Quartz特有的Cron表达式来确定某类时间,能完成类似"每个月二十号XXX,每个星期三XXX"之类的任务。
先对MyJob做个小的修改,时间用中文来输出,不然看起来太费劲,逻辑上没有任何修改。
- public class MyJob implements Job {
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- String jobName = context.getJobDetail().getKey().getName();
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
- System.out.println("任务Key:" + jobName + " 正在执行,执行时间: " + dateFormat.format(Calendar.getInstance().getTime()));
- }
- }
接下来创建QuartzCronTest.java,这里采用了CronTrigger作为触发器,注意NOTICE注释下面的代码:
- public class QuartzCronTest {
- public static void main(String[] args) throws Throwable {
- SchedulerFactory factory = new StdSchedulerFactory();
- Scheduler scheduler = factory.getScheduler();
- JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build();
- // @NOTICE
- // 与SimpleTrigger对比:类不同了,现在的是Trigger的子类CronTrigger;withSchedule中的参数变为CronScheduleBuilder了
- // CronScheduleBuilder可以通过类似"0/13 * * * * ?"这种表达式来创建定时任务
- // 当前这个表达式的定义是每个秒是13的倍数,或者是0的时候,都触发任务
- CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
- .withSchedule(CronScheduleBuilder.cronSchedule("0/13 * * * * ?")).build();
- scheduler.scheduleJob(job, trigger);
- scheduler.start();
- try {
- // 等待60秒查看效果
- Thread.sleep(60L * 1000L);
- } catch (Exception e) {
- }
- scheduler.shutdown(true);
- }
- }
- /*
- --------------------------------------
- 0 0 12 * * ? 每天12点触发
- 0 15 10 ? * * 每天10点15分触发
- 0 15 10 * * ? 每天10点15分触发
- 0 15 10 * * ? * 每天10点15分触发
- 0 15 10 * * ? 2005 2005年每天10点15分触发
- 0 * 14 * * ? 每天下午的 2点到2点59分每分触发
- 0 0/5 14 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发)
- 0 0/5 14,18 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发) 每天下午的 18点到18点59分(整点开始,每隔5分触发)
- 0 0-5 14 * * ? 每天下午的 2点到2点05分每分触发
- 0 10,44 14 ? 3 WED 3月分每周三下午的 2点10分和2点44分触发
- 0 15 10 ? * MON-FRI 从周一到周五每天上午的10点15分触发
- 0 15 10 15 * ? 每月15号上午10点15分触发
- 0 15 10 L * ? 每月最后一天的10点15分触发
- 0 15 10 ? * 6L 每月最后一周的星期五的10点15分触发
- 0 15 10 ? * 6L 2002-2005 从2002年到2005年每月最后一周的星期五的10点15分触发
- 0 15 10 ? * 6#3 每月的第三周的星期五开始触发
- 0 0 12 1/5 * ? 每月的第一个中午开始每隔5天触发一次
- 0 11 11 11 11 ? 每年的11月11号 11点11分触发(光棍节)
- --------------------------------------
- */
其实使用起来很简单,把Trigger的传入“升级”为CronTrigger就可以了,通过CronScheduleBuilder把"0 0 12 * * ?"这样的Cron表达式传入CronTrigger当中,任务就可以在指定的时间自动执行啦。