本文共 12219 字,大约阅读时间需要 40 分钟。
Quartz介绍
任务调度框架“Quartz”是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。 简单来说就是实现“计划(或定时)任务”的系统,例如:订单下单后未付款,15分钟后自动撤消订单,并自动解锁锁定的商品 Quartz的触发器 触发器用来告诉调度程序作业什么时候触发。框架提供了5种触发器类型,但两个最常用的SimpleTrigger 简单触发器和CronTrigger 表达式触发器。 五种类型的Trigger(定时器): SimpleTrigger,CronTirgger,DateIntervalTrigger,NthIncludedDayTrigger和Calendar类( org.quartz.Calendar)。 场景: SimpleTrigger:执行N次,重复N次 CronTrigger:几秒 几分 几时 哪日 哪月 哪周 哪年,执行 存储方式 RAMJobStore(内存作业存储类型)和JDBCJobStore(数据库作业存储类型), 两种方式对比如下: RAMJobStore: 优点: 不要外部数据库,配置容易,运行速度快 缺点:因为调度程序信息是存储在被分配给JVM的内存里面, 所以,当应用程序停止运行时,所有调度信息将被丢失。 另外因为存储到JVM内存里面,所以可以存储多少个Job和Trigger将会受到限制 JDBCJobStor: 优点:支持集群,因为所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务 缺点:运行速度的快慢取决与连接数据库的快慢 图解quartz工作流程 核心类和核心类之间关系 QuartzSchedulerThread:负责执行向QuartzScheduler注册的触发Trigger的工作的线程。 ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提供运行效率。 QuartzSchedulerResources:包含创建QuartzScheduler实例所需的所有资源(JobStore,ThreadPool等)。 SchedulerFactory:提供用于获取调度程序实例的客户端可用句柄的机制。 JobStore:通过类实现的接口,这些类要为org.quartz.core.QuartzScheduler的使用提供一个org.quartz.Job和org.quartz.Trigger存储机制。 作业和触发器的存储应该以其名称和组的组合为唯一性。 QuartzScheduler:这是Quartz的核心,它是org.quartz.Scheduler接口的间接实现,包含调度org.quartz.Jobs,注册org.quartz.JobListener实例等的方法。 Scheduler:这是Quartz Scheduler的主要接口,代表一个独立运行容器。调度程序维护JobDetails和触发器的注册表。 一旦注册,调度程序负责执行作业,当他们的相关联的触发器触发(当他们的预定时间到达时)。 Trigger:具有所有触发器通用属性的基本接口,描述了job执行的时间出发规则。 - 使用TriggerBuilder实例化实际触发器。 JobDetail:传递给定作业实例的详细信息属性。 JobDetails将使用JobBuilder创建/定义。 1.jobname+jobgroup=primary key identity 2.jobdetail每执行一次都会新建一个job实例 Job:示要执行的“作业”的类实现的接口。只有一个方法 void execute(jobExecutionContext context) (jobExecutionContext 提供调度上下文各种信息,运行时数据保存在jobDataMap中) Job有个子接口StatefulJob ,代表有状态任务。 有状态任务不可并发,前次任务没有执行完,后面任务处于阻塞等待 jobName+groupName=primary key注1:这里面最最重要的接口是Scheduler接口。它提供了简单的操作,例如:将任务纳入日程或者从日程中取消,开始/停止/暂停日程进度。 翻译:Scheduler的中文是:“调度程序,日程安排程序”
quartz相关表达式
SimpleTrigger介绍
每次执行 * 长时间,每次间隔 * 长时间 案例需要的功能 所需pom依赖org.springframework spring-aspects org.quartz-scheduler quartz 2.2.1 org.quartz-scheduler quartz-jobs 2.2.1
创建自定义RamJob
package com.zxp.quartz01.job;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;/** * @author笑笑 * @site www.xiaoxiao.com * @company * @create 2020-01-03 20:43 * * 创建自定义RamJob * 必须实现org.quartz.Job接口 * */public class RamJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.err.println("这里就是定时任务启动会执行的代码块"); }}
测试类
package com.zxp.quartz01.demo;import com.zxp.quartz01.job.RamJob;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import static org.quartz.JobBuilder.newJob;/** * @author笑笑 * @site www.xiaoxiao.com * @company * @create 2020-01-03 20:39 *Quartz简单触发器 * quartz的入门级案例 * 讲解quartz定时任务调用过程(基于内存) * schedulefactory、schedule、Trigger、jobdetail */public class Demo1 { public static void main(String[] args) throws Exception {// SchedulerFactory 提供用于获取调度程序实例的客户端可用句柄的机制。 SchedulerFactory schedulerFactory=new StdSchedulerFactory();// Scheduler 这是Quartz Scheduler的主要接口,代表一个独立运行容器。调度程序维护JobDetails和触发器的注册表。 Scheduler scheduler= schedulerFactory.getScheduler();// JobDetail 传递给定作业实例的详细信息属性。 JobDetails将使用JobBuilder创建/定义。 JobDetail jobDetail=newJob(RamJob.class)// 组成唯一标识 .withIdentity("job1","group1") .withDescription("这是第一个定时任务案例") .build();//构建触发器(存放定时任务执行规则) 使用TriggerBuilder实例化实际触发器。 Trigger trigger=(Trigger) TriggerBuilder.newTrigger()// 定时任务每六秒执行一次一共执行三次 .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(3,6)) .withIdentity("trigger1","group1") .withDescription("这是第一个触发器") .build();// 调度工厂绑定作业类及触发器 scheduler.scheduleJob(jobDetail,trigger);// 启动定时任务 scheduler.start(); }}
CronTirgger介绍
测试类package com.zxp.quartz01.demo;import com.zxp.quartz01.job.RamJob;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import static org.quartz.JobBuilder.newJob;/** * @author笑笑 * @site www.xiaoxiao.com * @company * @create 2020-01-03 20:39 * * quartz的入门级案例 * 讲解quartz定时任务调用过程(基于内存) * schedulefactory、schedule、Trigger、jobdetail * Quartz表达式触发器 * 表达式触发器比简单触发器灵活 * */public class Demo2 { public static void main(String[] args) throws Exception {// SchedulerFactory 提供用于获取调度程序实例的客户端可用句柄的机制。 SchedulerFactory schedulerFactory=new StdSchedulerFactory();// Scheduler 这是Quartz Scheduler的主要接口,代表一个独立运行容器。调度程序维护JobDetails和触发器的注册表。 Scheduler scheduler= schedulerFactory.getScheduler();// JobDetail 传递给定作业实例的详细信息属性。 JobDetails将使用JobBuilder创建/定义。 JobDetail jobDetail=newJob(RamJob.class)// 组成唯一标识 .withIdentity("job2","group1") .withDescription("这是第二个定时任务案例") .build();//构建触发器(存放定时任务执行规则) 使用TriggerBuilder实例化实际触发器。 Trigger trigger=(Trigger) TriggerBuilder.newTrigger()// 指定表达触发器规则 CronTirgger ("5/3 * * * * ?"))从第五秒开始每三秒执行一次,无上限// .withSchedule(CronScheduleBuilder.cronSchedule(" 5/3 * * * * ?"))// 定时定点执行 .withSchedule(CronScheduleBuilder.cronSchedule("0 23 21 * * ?")) .withIdentity("trigger2","group1") .withDescription("这是第一个触发器") .build();// 调度工厂绑定作业类及触发器 scheduler.scheduleJob(jobDetail,trigger);// 启动定时任务 scheduler.start(); }}
测试(“5/3 * * * * ?”))从第五秒开始每三秒执行一次,无上限
测试(“0 23 21 * * ?”)) 定时定点执行package com.zxp.quartz01.demo;import com.zxp.quartz01.job.RamJob;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import static org.quartz.JobBuilder.newJob;/** * @author笑笑 * @site www.xiaoxiao.com * @company * @create 2020-01-04 10:24 */public class Demo3 { public static void main(String[] args) throws SchedulerException { SchedulerFactory factory = new StdSchedulerFactory();// 调度器创建 Scheduler scheduler = factory.getScheduler();// 具体定时任务需要执行的代码 JobDetail jobDetail = newJob(RamJob.class) .withIdentity("job2", "group1") .withIdentity("这是一个作业类案例") .build(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); jobDataMap.put("name","學習"); jobDataMap.put("level","初級级"); jobDataMap.put("job","软件开发"); Trigger trigger = (Trigger) TriggerBuilder.newTrigger()// 每6s执行一次 .withSchedule(CronScheduleBuilder.cronSchedule("0/6 * * * * ?"))// 定时定点执行// .withSchedule(CronScheduleBuilder.cronSchedule("0 52 09 * * ?"))// 触发器标识 .withIdentity("trigger2", "group1") .withDescription("这是一个触发器") .build();// 调度工厂绑定作业类及触发器 scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); }}
package com.zxp.quartz01.job;import org.quartz.Job;import org.quartz.JobDataMap;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;/** * @author笑笑 * @site www.xiaoxiao.com * @company * @create 2020-01-03 20:43 * * 创建自定义RamJob * 必须实现org.quartz.Job接口 * */public class RamJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// System.err.println("这里就是定时任务启动会执行的代码块");// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// System.err.println(format.format(new Date())+" : 这是一个Quartz...");//// try {// Thread.sleep(20*1000);// System.out.println("模拟正在处理大数据....");// } catch (InterruptedException e) {// e.printStackTrace();// } JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); System.out.println(jobDataMap.get("name").toString() + jobDataMap.get("level").toString() + jobDataMap.get("job")); }}
測試
Spring task Vs Quartz Spring task: 优点:无需整合spring,作业类中就可以调用业务service 缺点:单线程;不能做数据存储型的定时任务 Quartz: 优点:多线程;可以做数据存储型的定时任务,维护性高; 缺点:需要整合spring,不能直接调用业务层service; 演示Spring task缺点package com.zxp.quartz01.task;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Service;import java.text.SimpleDateFormat;import java.util.Date;/** * @author笑笑 * @site www.xiaoxiao.com * @company * @create 2020-01-03 21:29 */@Servicepublic class SpringTask { @Scheduled(cron = "0/10 * * * * ?") public void xxx(){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.err.println(format.format(new Date())+" : 这是一个spring task..."); try { Thread.sleep(20*1000); System.out.println("模拟正在处理大数据...."); } catch (InterruptedException e) { e.printStackTrace(); } }}
测试类
package com.zxp.quartz01;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.scheduling.annotation.EnableScheduling;//spring task注解@EnableScheduling@SpringBootApplicationpublic class Quartz01Application { public static void main(String[] args) { SpringApplication.run(Quartz01Application.class, args); }}
结果是spring task中的定时任务变成了30s执行一次
演示Quartz代码package com.zxp.quartz01.demo;import com.zxp.quartz01.job.RamJob;import org.quartz.*;import org.quartz.impl.StdSchedulerFactory;import static org.quartz.JobBuilder.newJob;/** * @author笑笑 * @site www.xiaoxiao.com * @company * @create 2020-01-03 20:39 * * quartz的入门级案例 * 讲解quartz定时任务调用过程(基于内存) * schedulefactory、schedule、Trigger、jobdetail * Quartz表达式触发器 * 表达式触发器比简单触发器灵活 * */public class Demo2 { public static void main(String[] args) throws Exception {// SchedulerFactory 提供用于获取调度程序实例的客户端可用句柄的机制。 SchedulerFactory schedulerFactory=new StdSchedulerFactory();// Scheduler 这是Quartz Scheduler的主要接口,代表一个独立运行容器。调度程序维护JobDetails和触发器的注册表。 Scheduler scheduler= schedulerFactory.getScheduler();// JobDetail 传递给定作业实例的详细信息属性。 JobDetails将使用JobBuilder创建/定义。 JobDetail jobDetail=newJob(RamJob.class)// 组成唯一标识 .withIdentity("job2","group1") .withDescription("这是第二个定时任务案例") .build();//构建触发器(存放定时任务执行规则) 使用TriggerBuilder实例化实际触发器。 Trigger trigger=(Trigger) TriggerBuilder.newTrigger()// 指定表达触发器规则 CronTirgger ("5/3 * * * * ?"))从第五秒开始每三秒执行一次,无上限// .withSchedule(CronScheduleBuilder.cronSchedule(" 5/3 * * * * ?"))// 定时定点执行// .withSchedule(CronScheduleBuilder.cronSchedule("0 23 21 * * ?")) .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")) .withIdentity("trigger2","group1") .withDescription("这是第一个触发器") .build();// 调度工厂绑定作业类及触发器 scheduler.scheduleJob(jobDetail,trigger);// 启动定时任务 scheduler.start(); }}
RamJob
package com.zxp.quartz01.job;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;import java.util.Date;/** * @author笑笑 * @site www.xiaoxiao.com * @company * @create 2020-01-03 20:43 * * 创建自定义RamJob * 必须实现org.quartz.Job接口 * */public class RamJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// System.err.println("这里就是定时任务启动会执行的代码块"); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.err.println(format.format(new Date())+" : 这是一个Quartz..."); try { Thread.sleep(20*1000); System.out.println("模拟正在处理大数据...."); } catch (InterruptedException e) { e.printStackTrace(); } }}
结果:不管前一个定时任务的线程是否结束,都会开启下一个线程,依然每10s执行一次;
转载地址:http://hurzi.baihongyu.com/