01 Quartz-初识Quartz-样例入手
2019-05-20 本文已影响0人
花神子
quartz
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 2.3.0。
1、quartz简介
Quartz是一个完全由java编写的开源作业调度框架。使用非常简单。简单地创建一个实现org.quartz.Job接口的java类。Job接口包含唯一的方法:
public void execute(JobExecutionContext context) throws JobExecutionException;
Job接口实现类里面,添加一些逻辑到execute()方法。一旦你配置好Job实现类并设定好调度时间表,Quartz将密切注意剩余时间。当调度程序确定该是通知你的作业的时候,Quartz框架将调用你Job实现类(作业类)上的execute()方法并允许做它该做的事情。
2 入门实例
不管是使用什么SpringBoot还是其他框架我们都需要做一件事情就是需要添加pom依赖
<dependencies>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
第一步 编写我们需要处理的任务逻辑
- 样例中其实只是简单的做了一行日志输出(输出线程名以及job信息),代替业务逻辑。
package com.maozw.quartz.job;
import org.quartz.*;
/**
*
*
* @description
* @see
* @author maozhengwei
* @data 2019-05-16 13:10
* @version V1.0.0
**/
public class MyJob implements Job {
/**
* <p>
* Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code>
* fires that is associated with the <code>Job</code>.
* </p>
*
* <p>
* The implementation may wish to set a
* {@link JobExecutionContext#setResult(Object) result} object on the
* {@link JobExecutionContext} before this method exits. The result itself
* is meaningless to Quartz, but may be informative to
* <code>{@link JobListener}s</code> or
* <code>{@link TriggerListener}s</code> that are watching the job's
* execution.
* </p>
*
* @param context
* @throws JobExecutionException if there is an exception while executing the job.
*/
public void execute(JobExecutionContext context) throws JobExecutionException {
String name = context.getJobDetail().getKey().getName();
String group = context.getJobDetail().getKey().getGroup();
System.out.println(Thread.currentThread().getName() + " > > > > MyJob.execute " + "name :" +name+ " group :" + group);
}
}
第二步 获取调度Scheduler实例,进行初始化
- 样例中我简单做了下封装,仅此而已:
package com.maozw.quartz.scheduler;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Date;
/**
*
*
* @description
* @see
* @author maozhengwei
* @data 2019-05-16 14:15
* @version V1.0.0
**/
public class QuartzScheduler {
/**
* 定义 全局 Scheduler 方便以下方法使用
*/
private static Scheduler scheduler;
/**Scheduler
* 初始化
*/
static {
try {
scheduler = getSechduler();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 获取Scheduler instance
* 实际生产中不建议这么做:最好采用资源隔离的方式;避免任务过多进行资源抢占导致任务misfire
* @return
* @throws SchedulerException
*/
public static Scheduler getSechduler() throws SchedulerException {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
if (scheduler == null) {
synchronized (QuartzScheduler.class) {
if (scheduler == null) {
scheduler = schedulerFactory.getScheduler();
}
}
}
return scheduler;
}
/**
* add Job
* 这里可以作为通用型,可以定制job以及不同Job不同的启动参数,采用适配器模式去适配不同的触发器
* @param jobGroup
* @param jobName
* @param jobClass
* @throws SchedulerException
*/
public void addJob(String jobGroup, String jobName, Class jobClass) throws SchedulerException {
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();
// 创建触发器
// withIntervalInSeconds(2)表示每隔2s执行任务
Date triggerDate = new Date();
SimpleScheduleBuilder schedBuilder = SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)
.repeatForever();
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder
.newTrigger()
.withIdentity(jobName, jobGroup);
Trigger trigger = triggerBuilder
.startAt(triggerDate)
.withSchedule(schedBuilder)
.build();
// 将job trigger放入scheduler
scheduler.scheduleJob(jobDetail, trigger);
}
/**
* start scheduler
* @throws SchedulerException
*/
public void start() throws SchedulerException {
if (scheduler.isStarted()){
return;
}
scheduler.start();
}
}
第三步 启动
- 样例中使用main方法:
/**
* @description
* @see
* @author maozhengwei
* @data 2019-05-16 13:08
* @version V1.0.0
**/
public class QuartzApplication {
public static void main(String[] args) throws SchedulerException {
QuartzScheduler quartzScheduler = new QuartzScheduler();
quartzScheduler.addJob("g1","n1", MyJob.class);
quartzScheduler.addJob("g2","n2", MyJob.class);
quartzScheduler.start();
}
}
第五步 输出结果
其实我们从输出结果也能看到一些东西:
-
不是每次都是同一个线程在执行任务;
-
结果来看默认的线程池大小是10
DefaultQuartzScheduler_Worker-1 > > > > MyJob.execute name :n1 group :g1
DefaultQuartzScheduler_Worker-2 > > > > MyJob.execute name :n2 group :g2
DefaultQuartzScheduler_Worker-3 > > > > MyJob.execute name :n1 group :g1
DefaultQuartzScheduler_Worker-4 > > > > MyJob.execute name :n2 group :g2
DefaultQuartzScheduler_Worker-5 > > > > MyJob.execute name :n1 group :g1
DefaultQuartzScheduler_Worker-6 > > > > MyJob.execute name :n2 group :g2
DefaultQuartzScheduler_Worker-7 > > > > MyJob.execute name :n1 group :g1
DefaultQuartzScheduler_Worker-8 > > > > MyJob.execute name :n2 group :g2
DefaultQuartzScheduler_Worker-9 > > > > MyJob.execute name :n1 group :g1
DefaultQuartzScheduler_Worker-10 > > > > MyJob.execute name :n2 group :g2
DefaultQuartzScheduler_Worker-1 > > > > MyJob.execute name :n1 group :g1
DefaultQuartzScheduler_Worker-2 > > > > MyJob.execute name :n2 group :g2
DefaultQuartzScheduler_Worker-3 > > > > MyJob.execute name :n1 group :g1
DefaultQuartzScheduler_Worker-4 > > > > MyJob.execute name :n2 group :g2
为了证明这个猜测 我们看一下:这俩先不做源码分析:只是简单的看看:quartz 默认帮我们做了哪些工作;我们在quartz 的源码包里找到如下文件:quartz.properties
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
我们可以看到
-
org.quartz.threadPool.threadCount: 10
-
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
这也应征了我们猜测。
OK !