Quartz简介及应用场景
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:不要外部数据库,配置容易,运行速度快
JDBCJobStore:支持集群,因为所有的任务信息都会保存 运行速度的快慢取决与连接数据库的快慢
缺点:
RAMJobStore:因为调度程序信息是存储在被分配给JVM的内存里面,所以,当应用程序停止运行时,所有调度信息将被丢失。另外因为存储到JVM内存里面,所以可以存储多少个Job和Trigger将会受到限制
JDBCJobStore:到数据库中,可以控制事物,还有就是如 果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务
图解quartz工作流程
Quartz在线生成表达式网址:http://cron.qqe2.com/
新建项目
所需pom依赖
1 <dependency> 2 <groupId>org.springframework</groupId> 3 <artifactId>spring-aspects</artifactId> 4 </dependency> 5 <dependency> 6 <groupId>org.quartz-scheduler</groupId> 7 <artifactId>quartz</artifactId> 8 <version>2.2.1</version> 9 </dependency> 10 <dependency> 11 <groupId>org.quartz-scheduler</groupId> 12 <artifactId>quartz-jobs</artifactId> 13 <version>2.2.1</version> 14 </dependency>
Quartz简单触发器 SimpleTrigger介绍
每次执行 * 长时间,每次间隔 * 长时间
1 package com.javaqi.quartz01.quartz; 2 3 import com.javaqi.quartz01.job.RamJob; 4 import org.quartz.*; 5 import org.quartz.impl.StdSchedulerFactory; 6 7 import static org.quartz.JobBuilder.newJob; 8 9 /** 10 * @author XuFanQi 11 * @site 12 * @company 13 * @create 2019-12-01 19:16 14 */ 15 public class Demo1 { 16 public static void main(String[] args) throws Exception { 17 18 SchedulerFactory factory = new StdSchedulerFactory(); 19 // 调度器创建 20 Scheduler scheduler = factory.getScheduler(); 21 22 // 作业类 23 // 具体定时任务需要执行的代码 24 JobDetail jobDetail = newJob(RamJob.class) 25 .withIdentity("job1","group1") 26 .withIdentity("this is a job1") 27 .build(); 28 29 // 触发器 30 Trigger trigger = (Trigger) TriggerBuilder.newTrigger() 31 // 重复3次间隔6秒 32 .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(3,6)) 33 // 触发器标识 34 .withIdentity("trigger1","group1") 35 .withDescription("this is a trigger1") 36 .build(); 37 38 // 调度工厂绑定作业类及触发器 39 scheduler.scheduleJob(jobDetail,trigger); 40 scheduler.start(); 41 } 42 43 }
Quartz表达式触发器CronTirgger介绍
定时定点
.withSchedule(CronScheduleBuilder.cronSchedule("0 26 19 * * ?"))
1 package com.javaqi.quartz01.quartz; 2 3 import com.javaqi.quartz01.job.RamJob; 4 import org.quartz.*; 5 import org.quartz.impl.StdSchedulerFactory; 6 7 import static org.quartz.JobBuilder.newJob; 8 9 /** 10 * @author XuFanQi 11 * @site 12 * @company 13 * @create 2019-12-01 19:18 14 * 15 * 表达式触发器 16 * 定时定点 17 */ 18 public class Demo2 { 19 public static void main(String[] args) throws Exception { 20 21 SchedulerFactory factory = new StdSchedulerFactory(); 22 // 调度器创建 23 Scheduler scheduler = factory.getScheduler(); 24 25 // 作业类 26 // 具体定时任务需要执行的代码 27 JobDetail jobDetail = newJob(RamJob.class) 28 .withIdentity("job1","group1") 29 .withIdentity("this is a job1") 30 .build(); 31 32 // 触发器 33 Trigger trigger = (Trigger) TriggerBuilder.newTrigger() 34 // 重复3次间隔6秒 35 .withSchedule(CronScheduleBuilder.cronSchedule("0 26 19 * * ?")) 36 // 触发器标识 37 .withIdentity("trigger1","group1") 38 .withDescription("this is a trigger1") 39 .build(); 40 41 // 调度工厂绑定作业类及触发器 42 scheduler.scheduleJob(jobDetail,trigger); 43 scheduler.start(); 44 } 45 46 }
遵循某一规律循环执行,不限次数
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
1 package com.javaqi.quartz01.quartz; 2 3 import com.javaqi.quartz01.job.RamJob; 4 import org.quartz.*; 5 import org.quartz.impl.StdSchedulerFactory; 6 7 import static org.quartz.JobBuilder.newJob; 8 9 /** 10 * @author XuFanQi 11 * @site 12 * @company 13 * @create 2019-12-01 19:18 14 * 15 * 表达式触发器 16 */ 17 public class Demo3 { 18 public static void main(String[] args) throws Exception { 19 20 SchedulerFactory factory = new StdSchedulerFactory(); 21 // 调度器创建 22 Scheduler scheduler = factory.getScheduler(); 23 24 // 作业类 25 // 具体定时任务需要执行的代码 26 JobDetail jobDetail = newJob(RamJob.class) 27 .withIdentity("job1","group1") 28 .withIdentity("this is a job1") 29 .build(); 30 31 // 触发器 32 Trigger trigger = (Trigger) TriggerBuilder.newTrigger() 33 // 重复3次间隔6秒 34 .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")) 35 // 触发器标识 36 .withIdentity("trigger1","group1") 37 .withDescription("this is a trigger1") 38 .build(); 39 40 // 调度工厂绑定作业类及触发器 41 scheduler.scheduleJob(jobDetail,trigger); 42 scheduler.start(); 43 } 44 45 }
Quartz中参数传递
1 package com.javaqi.quartz01.quartz; 2 3 import com.javaqi.quartz01.job.RamJob; 4 import org.quartz.*; 5 import org.quartz.impl.StdSchedulerFactory; 6 7 import static org.quartz.JobBuilder.newJob; 8 9 /** 10 * @author XuFanQi 11 * @site 12 * @company 13 * @create 2019-12-01 19:18 14 * 15 * 参数传递 16 */ 17 public class Demo4 { 18 public static void main(String[] args) throws Exception { 19 20 SchedulerFactory factory = new StdSchedulerFactory(); 21 // 调度器创建 22 Scheduler scheduler = factory.getScheduler(); 23 24 // 作业类 25 // 具体定时任务需要执行的代码 26 JobDetail jobDetail = newJob(RamJob.class) 27 .withIdentity("job1","group1") 28 .withIdentity("this is a job1") 29 .build(); 30 JobDataMap jobDataMap = jobDetail.getJobDataMap(); 31 jobDataMap.put("name","王五"); 32 jobDataMap.put("level","OoO"); 33 jobDataMap.put("job","Oooo"); 34 35 36 // 触发器 37 Trigger trigger = (Trigger) TriggerBuilder.newTrigger() 38 // 重复3次间隔6秒 39 .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")) 40 // 触发器标识 41 .withIdentity("trigger1","group1") 42 .withDescription("this is a trigger1") 43 .build(); 44 45 // 调度工厂绑定作业类及触发器 46 scheduler.scheduleJob(jobDetail,trigger); 47 scheduler.start(); 48 } 49 50 }
RamJob
1 package com.javaqi.quartz01.job; 2 3 import org.quartz.Job; 4 import org.quartz.JobExecutionContext; 5 import org.quartz.JobExecutionException; 6 7 import java.text.SimpleDateFormat; 8 import java.util.Date; 9 10 /** 11 * @author XuFanQi 12 * @site 13 * @company 14 * @create 2019-12-01 18:57 15 */ 16 public class RamJob implements Job { 17 @Override 18 public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { 19 20 System.out.println("定时任务!!!..."); 21 JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); 22 System.out.println(jobDataMap.get("name").toString() + jobDataMap.get("level").toString() + jobDataMap.get("job")); 23 24 25 26 27 } 28 29 }
Spring task Vs Quartz
Spring task
优点:无需整合spring,作业类中就可以调用业务service
缺点:单线程;不能做数据存储型的定时任务
Quartz
优点:多线程;可以做数据存储型的定时任务,维护性高;
缺点:需要整合spring,不能直接调用业务层service;
线程论证代码
Spring task代码
1 package com.javaqi.quartz01.task; 2 3 import org.springframework.scheduling.annotation.Scheduled; 4 import org.springframework.stereotype.Component; 5 6 import java.text.SimpleDateFormat; 7 import java.util.Date; 8 9 /** 10 * @author XuFanQi 11 * @site 12 * @company 13 * @create 2019-12-01 19:38 14 */ 15 @Component 16 public class SpringTask { 17 18 @Scheduled(cron = "0/10 * * * * ?") 19 public void xxx(){ 20 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 21 System.err.println(format.format(new Date())+" : 这是一个spring task..."); 22 23 try { 24 Thread.sleep(20*1000); 25 System.out.println("模拟正在处理大数据...."); 26 } catch (InterruptedException e) { 27 e.printStackTrace(); 28 } 29 } 30 }
spring task 单线程
结果是spring task中的定时任务变成了30s执行一次
Quartz代码
RamJob
1 package com.javaqi.quartz01.job; 2 3 import org.quartz.Job; 4 import org.quartz.JobExecutionContext; 5 import org.quartz.JobExecutionException; 6 7 import java.text.SimpleDateFormat; 8 import java.util.Date; 9 10 /** 11 * @author XuFanQi 12 * @site 13 * @company 14 * @create 2019-12-01 18:57 15 */ 16 public class RamJob implements Job { 17 @Override 18 public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { 19 20 // System.out.println("定时任务!!!..."); 21 // JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); 22 // System.out.println(jobDataMap.get("name").toString() + jobDataMap.get("level").toString() + jobDataMap.get("job")); 23 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 24 System.err.println(format.format(new Date())+" : 基于RAM的quartz调度框架定时任务..."); 25 26 try { 27 Thread.sleep(20*1000); 28 System.out.println("模拟正在处理大数据...."); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 34 }
Demo5
1 package com.javaqi.quartz01.quartz; 2 3 import com.javaqi.quartz01.job.RamJob; 4 import org.quartz.*; 5 import org.quartz.impl.StdSchedulerFactory; 6 7 import static org.quartz.JobBuilder.newJob; 8 9 /** 10 * @author XuFanQi 11 * @site 12 * @company 13 * @create 2019-12-01 19:53 14 */ 15 public class Demo5 { 16 public static void main(String[] args) throws SchedulerException { 17 SchedulerFactory factory = new StdSchedulerFactory(); 18 // 调度器创建 19 Scheduler scheduler = factory.getScheduler(); 20 21 // 具体定时任务需要执行的代码 22 JobDetail jobDetail = newJob(RamJob.class) 23 .withIdentity("job2", "group1") 24 .withIdentity("这是一个作业类案例") 25 .build(); 26 27 Trigger trigger = (Trigger) TriggerBuilder.newTrigger() 28 // 每10s执行一次 29 .withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")) 30 // 触发器标识 31 .withIdentity("trigger2", "group1") 32 .withDescription("这是一个触发器") 33 .build(); 34 35 // 调度工厂绑定作业类及触发器 36 scheduler.scheduleJob(jobDetail, trigger); 37 scheduler.start(); 38 } 39 }