最近在准备做一个生日提醒的Demo,于是有了这篇博客。咳咳,虽然可以在手机日历设置提醒,但是我们要有自力更生的觉悟以及能力,自己能做当然用自己的嘛。
一、初步了解
百度百科是这样介绍Quartz这个项目的。
Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。
虽然我们可以使用Java的Timer以及线程来实现,但是却不太方便的精确的定位到某年某日某时某分某秒。所以对于这样的需求,使用Quartz是最好的选择
二、引入jar包
网上部分博客说
要使用Quartz,必须要引入以下这几个包:
1、log4j-1.2.16 2、quartz-2.1.7 3、slf4j-api-1.6.1.jar 4、slf4j-log4j12-1.6.1.jar
这些jar包都在Quartz的包内包含,不过似乎都引入会出现一些冲突,我使用的是2.2.3的jar包,当我引入quartz和log4j的jar,时候发生了冲突。最后引入的jar包如下:
注意,我的项目是Java项目,不是J2EE。
三、添加要被执行的任务类
这个类的execute()方法会在触发器被触发的时候执行,即到了预设时间时会被执行。
package Toolkit;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
System.out.println("现在时间是:" + simpleDateFormat.format(new Date()));
System.out.println("JobExecutionContext内容是:" + jobExecutionContext.getJobDetail());
}
}
四、创建、执行任务调度
话不多说,都在代码里~
import Toolkit.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
public class Main {
public void start(){
//第一步,必需要取得一个调度器
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
try {
//任务调度器
Scheduler scheduler = schedulerFactory.getScheduler();
//第二步,获取JobDetail对象,来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息
JobDetail job = newJob(MyJob.class).withIdentity("job1", "group1").build();
//复杂的Trigger
//job1将 从0秒开始 每隔20秒执行一次
//第三步,获取trigger
CronTrigger trigger1 = newTrigger()
.withIdentity("trigger1","group1")
.withSchedule(cronSchedule("0/20 * * * * ?"))
.build();
//第四步,将trigger和job绑定,一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。
Date date = scheduler.scheduleJob(job,trigger1);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(job.getKey() + "已经被安排执行于:" + simpleDateFormat.format(date) + ",并且以如下重复规则重复执行" + trigger1.getCronExpression() + ",trigger为:" + trigger1.getKey().getName());
// 开始执行,start()方法被调用后,计时器就开始工作
scheduler.start();
try {
//主线程等待十分钟
Thread.sleep(60L * 10000L);
} catch (Exception e) { }
//关闭定时调度,定时器不再工作
scheduler.shutdown(true);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public static void main(String args[]){
Main main = new Main();
main.start();
}
}
其中有两点需要详细说一说:
1.0/20 * * * * ?
,有关通配符的含义请戳这里!
2.一个Job可以绑定多个Trigger,一个Trigger只能绑定在一个Job上。
话不多说,都在代码里。下面给出一个Job绑定多个Trigger的Demo。
import Toolkit.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
public class Main {
public void start(){
//第一步,必需要取得一个调度器
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
try {
//任务调度器
Scheduler scheduler = schedulerFactory.getScheduler();
//第二步,获取JobDetail对象,来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息
JobDetail job = newJob(MyJob.class).withIdentity("job1", "group1").build();
//复杂的Trigger
//job1将 从0秒开始 每隔20秒执行一次
//第三步,获取trigger
CronTrigger trigger1 = newTrigger()
.withIdentity("trigger1","group1")
.withSchedule(cronSchedule("0 35 20 4 9 ?"))
.build();
//注意这里,多个Trigger绑定到一个Job上
CronTrigger trigger2 = newTrigger()
.withIdentity("trigger2","group1")
.forJob("job1","group1")
.withSchedule(cronSchedule("0/5 * * * * ?"))
.build();
//第四步,将trigger和job绑定,一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。
Date date = scheduler.scheduleJob(job,trigger1);
//注意这里,多个Trigger绑定到一个Job上
Date date1 = scheduler.scheduleJob(trigger2);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(job.getKey() + "已经被安排执行于:" + simpleDateFormat.format(date) + ",并且以如下重复规则重复执行" + trigger1.getCronExpression() + ",trigger为:" + trigger1.getKey().getName());
System.err.println(job.getKey() + "已经被安排执行于:" + simpleDateFormat.format(date1) + ",并且以如下重复规则重复执行" + trigger2.getCronExpression() + ",trigger为:" + trigger2.getKey().getName());
// 开始执行,start()方法被调用后,计时器就开始工作,计时调度中允许放入多个Job
scheduler.start();
try {
//主线程等待十分钟
Thread.sleep(60L * 10000L);
} catch (Exception e) { }
//关闭定时调度,定时器不再工作
scheduler.shutdown(true);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public static void main(String args[]){
Main main = new Main();
main.start();
}
}
CronTrigger配置格式:
格式: [秒] [分] [小时] [日] [月] [周] [年]
序号 | 说明 | 是否必填 | 允许填写的值 | 允许的通配符 |
1 | 秒 | 是 | 0-59 | , - * / |
2 | 分 | 是 | 0-59 | , - * / |
3 | 小时 | 是 | 0-23 | , - * / |
4 | 日 | 是 | 1-31 | , - * ? / L W |
5 | 月 | 是 | 1-12 or JAN-DEC | , - * / |
6 | 周 | 是 | 1-7 or SUN-SAT | , - * ? / L # |
7 | 年 | 否 | empty 或 1970-2099 | , - * / |
事例:
CronTrigger配置内容 | 含义 |
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分触发(光棍节) |