Quartz 是以模块的方式构建的,Job 和 Trigger 之间的结合需要靠 Scheduler。
创建
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
创建是通过 Quartz 默认的 SchedulerFactory,我们可以使用自定义参数(Properties)来创建和初始化 Quartz 调度器,配置参数一般存储在 quartz.properties 中。
我们上面是通过 scheduleJob() 方法来结合 Job和 Trigger,这个方法有个时间类型的返回值,我们可以获取到调度器开始的时间:
Date date = scheduler.scheduleJob(jobDetail, trigger);
关联完任务和触发器,我们就可以启动任务调度了:
scheduler.start();
将任务调度挂起(暂停):
scheduler.standby();
将任务关闭:
shutdown(true);//表示等待所有正在执行的job执行完毕之后,再关闭Scheduler
shutdown(false);//表示直接关闭Scheduler
我们再来了解下 quartz.properties 文件,先看一个示例:
也可以编写程序代码操作quartz.properties文件的内容:
public class QuartzProperties {
public static void main(String[] args) {
// 创建工厂实例
StdSchedulerFactory factory = new StdSchedulerFactory();
// 创建配置工厂的属性对象
Properties props = new Properties();
props.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS, "org.quartz.simpl.SimpleThreadPool"); // 线程池定义
props.put("org.quartz.threadPool.threadCount", "5"); // 默认Scheduler的线程数
try {
// 使用定义的属性初始化工厂
factory.initialize(props);
Scheduler scheduler = factory.getScheduler();
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
通过Properties设置工厂属性的缺点在用硬编码,假如需要修改例子中线程数量,将不得不修改代码,然后重新编译,所以不推荐使用。
三、Quartz 监听器
在 Quartz 实战中我们了解到三个核心模块分别是 Job、Trigger、Scheduler,既然 Quartz中存在监听器,相应的,这三者也分别有对应的监听器。监听器的作用便是用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知
1. JobListener
任务调度中,与任务 Job 相关的事件包括: Job 开始要执行的提示,执行完成的提示,接口如下:
1)方法解析
getName():用于获取改JobListener 的名称
jobToBeExecuted():Scheduler 在 JobDetail 将要被执行时调用这个方法
``jobExecutionVetoed()`:Scheduler 在 JobDetail 即将被执行,但又被 TriggerListener 否决时会调用该方法
jobWasExecuted():Scheduler 在 JobDetail 被执行之后调用这个方法
2)示例
Job 任务类:
@Slf4j
@PersistJobDataAfterExecution
public class TestJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext){
System.out.println("TestJob 执行啦");
}
}
JobListener :
public class MyJobListener implements JobListener {
@Override
public String getName() {
String name = getClass().getSimpleName();
System.out.println("监听器的名称是:" + name);
return name;
}
@Override
public void jobToBeExecuted(JobExecutionContext context) {
String jobName = context.getJobDetail().getKey().getName();
System.out.println("Job的名称是:" + jobName + "\tScheduler在JobDetail将要被执行时调用这个方法");
}
@Override
public void jobExecutionVetoed(JobExecutionContext context) {
String jobName = context.getJobDetail().getKey().getName();
System.out.println("Job的名称是:" + jobName + "\tScheduler在JobDetail即将被执行,但又被TriggerListerner否决时会调用该方法");
}
@Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
String jobName = context.getJobDetail().getKey().getName();
System.out.println("Job的名称是:" + jobName + "\tScheduler在JobDetail被执行之后调用这个方法");
}
}
任务调度类:
@Slf4j
public class TestScheduler {
public static void main(String[] args) throws Exception {
// 获取任务调度的实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 定义任务调度实例, 并与TestJob绑定
JobDetail jobDetail = JobBuilder.newJob(TestJob.class)
.usingJobData("executeCount", 0)
.withIdentity("testJob", "testJobGroup")
.build();
// 定义触发器, 会马上执行一次, 接着5秒执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.usingJobData("testInfo", "trigger数据存放")
.withIdentity("testTrigger", "testTriggerGroup")
.startNow()
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))
.build();
// 创建并注册一个全局的Job Listener
scheduler.getListenerManager()
.addJobListener(new MyJobListener(),
EverythingMatcher.allJobs());
// 使用触发器调度任务的执行
scheduler.scheduleJob(jobDetail, trigger);
// 开启任务
scheduler.start();
}
}
/** OUTPUT:
监听器的名称是:MyJobListener
Job的名称是:testJob Scheduler在JobDetail将要被执行时调用这个方法
TestJob 执行啦
监听器的名称是:MyJobListener
Job的名称是:testJob Scheduler在JobDetail被执行之后调用这个方法
**/