首先,我使用的quartz的版本
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
首先,main函数
public static void main(String[] args) throws SchedulerException {
//1.创建schedulerFactory的工厂
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
//2.从工厂中获取调度器实例
Scheduler scheduler = schedulerFactory.getScheduler();
//创建JobDetail
JobDetail jobDetail = JobBuilder.newJob(RAMJob.class)
.withDescription("this is a ram job")
.withIdentity("ramjob","ramGroup")
.build();
//任务运行的时间,simpleSchedle类型触发器有效
long time = System.currentTimeMillis() + 3 * 1000L;
Date startTime = new Date(time);
//创建Trigger
//使用SimpleScheduleBuilder或者CronSchedulerBuilder
Trigger trigger = TriggerBuilder.newTrigger()
.withDescription("触发器")
.withIdentity("ramTrigger","ramTriggerGroup")
.startAt(startTime)
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
//注册任务和定时器
scheduler.scheduleJob(jobDetail,trigger);
//启动调度器
scheduler.start();
log.info("启动时间:"+sdf.format(new Date()));
}
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
创建作业调度的工厂类:
首先看StdSchedulerFactory
constants:变量
太多了,等会用到再来看
constructors:构造方法
/**
生成一个没有未初始化的StdSchedulerFactory
*/
public StdSchedulerFactory()
/**
下面这两个,其实是一个直接的Properties类型的,另一个是这个properties的fileName,
其实就是通过InputStream解析这个文件将封装一个出properties,最后还是通过 initialize(props);
给变量:private PropertiesParser cfg;赋值
this.cfg = new PropertiesParser(props);
*/
public StdSchedulerFactory(Properties props) throws SchedulerException {
initialize(props);
}
public StdSchedulerFactory(String fileName) throws SchedulerException {
initialize(fileName);
}
Scheduler scheduler = schedulerFactory.getScheduler();
public Scheduler getScheduler() throws SchedulerException {
if (cfg == null) {
initialize();//此次会去解析是否有quartz.proterties文件,如果有则用你的,如果没有,那就会用他jar包中的
在org/quartz/quartz.properties
/**
By default a properties file named "quartz.properties" is loaded from
* the 'current working directory'. If that fails, then the
* "quartz.properties" file located (as a resource) in the org/quartz
* package is loaded. If you wish to use a file other than these defaults,
* you must define the system property 'org.quartz.properties' to point to
* the file you want.
*/
//quartz.properties中大致涉及:线程池中的线程数,线程优先级,具体可以看
// https://www.jianshu.com/p/14f86c6efe22
}
SchedulerRepository schedRep = SchedulerRepository.getInstance();
Scheduler sched = schedRep.lookup(getSchedulerName());
if (sched != null) {
if (sched.isShutdown()) {
schedRep.remove(getSchedulerName());
} else {
return sched;
}
}
sched = instantiate();
return sched;
}
//会生成一个Scheduler接口实现的的StdScheduler
在StdScheduler中有个变量:
private QuartzScheduler sched;
This is the heart of Quartz, an indirect implementation of the <code>{@link org.quartz.Scheduler}</code>
quartz的中心,间接的实现了Scheduler接口
StdScheduler里面的调用方法,都是使用QuartzScheduler里面的方法
划重点QuartzScheduler这个类,有点复杂,后面再讲
下面看JobDetail
关于Jobdetail和Trigger的介绍
/**
Quartz does not store an actual instance of a <code>Job</code> class, but
* instead allows you to define an instance of one, through the use of a <code>JobDetail</code>.
quartz中不保存一个真实的job类,但是可以通过jobdetail来定义一个实例
* <code>Job</code>s have a name and group associated with them, which
* should uniquely identify them within a single <code>{@link Scheduler}</code>.
job需要一个name和group来关联他们,
<code>Trigger</code>s are the 'mechanism' by which <code>Job</code>s
* are scheduled. Many <code>Trigger</code>s can point to the same <code>Job</code>,
* but a single <code>Trigger</code> can only point to one <code>Job</code>.
触发器是jobs的调度的机制。一个job可以对应多个Trigger,但是trigger只可以对应一个job
*/
//创建JobDetail
JobDetail jobDetail = JobBuilder.newJob(RAMJob.class)
.withDescription("this is a ram job")
.withIdentity("ramjob","ramGroup")
.build();
使用构造器模式:
新建一个JobDetailImpl
//创建Trigger
//使用SimpleScheduleBuilder或者CronSchedulerBuilder
Trigger trigger = TriggerBuilder.newTrigger()
.withDescription("触发器")
.withIdentity("ramTrigger","ramTriggerGroup")
.startAt(startTime)
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
其中在TriggerBuilder中的withSchedule()方法
/**
* Set the {@link ScheduleBuilder} that will be used to define the
* Trigger's schedule.
*
* <p>The particular <code>SchedulerBuilder</code> used will dictate
* the concrete type of Trigger that is produced by the TriggerBuilder.</p>
* @param schedBuilder the SchedulerBuilder to use.
* @return the updated TriggerBuilder
* @see ScheduleBuilder
* @see SimpleScheduleBuilder
* @see CronScheduleBuilder
* @see CalendarIntervalScheduleBuilder
*
是根据里面,来确定Trigger接口实现类的类型
其中,这个cron里面的解析"0/2 * * * * ?":是通过CronExpression.java中的buildExpression方法来解析的
在CronTriggerImpl中会
@Deprecated
public CronTriggerImpl(String name, String group, String cronExpression)
throws ParseException {
super(name, group);//name和group
setCronExpression(cronExpression);//解析cron字符串
setStartTime(new Date());//当前时间
setTimeZone(TimeZone.getDefault());//当前时区
}
//注册任务和定时器
scheduler.scheduleJob(jobDetail,trigger);
其实是调用的是QuartzScheduler中的 public Date scheduleJob(JobDetail jobDetail,
Trigger trigger) throws SchedulerException方法
resources.getJobStore().storeJobAndTrigger(jobDetail, trig);//存储job and trigger到jobStore
notifySchedulerListenersJobAdded(jobDetail);//添加jobDetail到调度监听器
notifySchedulerThread(trigger.getNextFireTime().getTime());//通知调度器下一刻调度时间
notifySchedulerListenersSchduled(trigger);//添加trigger到调度监听器
//启动调度器
scheduler.start();
public void start() throws SchedulerException {
if (shuttingDown|| closed) {
throw new SchedulerException(
"The Scheduler cannot be restarted after shutdown() has been called.");
}
// QTZ-212 : calling new schedulerStarting() method on the listeners
// right after entering start()
notifySchedulerListenersStarting();//通知调度监听器正在启动
if (initialStart == null) {
initialStart = new Date();
this.resources.getJobStore().schedulerStarted(); //
startPlugins();
} else {
resources.getJobStore().schedulerResumed();
}
schedThread.togglePause(false);
getLog().info(
"Scheduler " + resources.getUniqueIdentifier() + " started.");
notifySchedulerListenersStarted();//通知调度监听器已经启动
}
start()这个方法明天再看,回去看QGhappy vs BA黑凤梨
2018.10.10卖萌日