Quartz框架
轻量级的任务调度框架,支持作业调度、持久化、任务持久化、并发控制、失败重试等。与spring自带定时任务最主要的区别是他支持定时年月日时分秒存储
核心组件
调度器:Scheduler 任务 :Job 触发器:Trigger,包括SimpleTrigger和CronTrigger
- Job(任务):是一个接口,有一个方法
void execute(JobExecutionContext context)
,可以通过实现该接口来定义需要执行的任务(具体的逻辑代码)。
- JobDetail:Quartz每次执行Job时,都重新创建一个Job实例,会接收一个Job实现类,以便运行的时候通过
newInstance()
的反射调用机制去实例化Job。JobDetail是用来描述Job实现类以及相关静态信息,比如任务在scheduler中的组名等信息。
- Trigger(触发器):描述触发Job执行的时间触发规则实现类SimpleTrigger和CronTrigger可以通过crom表达式定义出各种复杂的调度方案。
- Calendar:是一些日历特定时间的集合。一个Trigger可以和多个 calendar关联,比如每周一早上10:00执行任务,法定假日不执行,则可以通过calendar进行定点排除。
- Scheduler(调度器):代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。Scheduler可以将Trigger绑定到某一JobDetail上,这样当Trigger被触发时,对应的Job就会执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。
Scheduler 调度器 -> Trigger 触发器-> JobDetail 工作策略 ->Job 工作
Quartz框架的工作流程
Quartz框架的工作流程如下:
- 首先,定义需要执行的任务(Job),并指定任务的执行规则(Trigger)。
- 其次,将任务和触发器注册到调度器中。
- 最后,调度器按照指定的条件和规则执行任务。
使用
-
导入依赖
xml
代码解读
复制代码
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-quartz --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
-
实现定时业务逻辑
创建一个业务类,继承 job 接口,并实现 execute() 方法,方法中即可实现相应业务逻辑
整理了一份面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】即可免费获取
java
代码解读
复制代码
import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class AlphaJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { // 业务逻辑代码略 } }
-
编写触发器类
定义任务的调度规则,实现Trigger接口。
java
代码解读
复制代码
public class HelloScheduler { public static void main(String[] args) throws SchedulerException { //1.创建一个jobDetail的实例,将该实例与HelloJob Class绑定 JobDetail jobDetail = JobBuilder .newJob(HelloJob.class) //定义Job类为HelloJob类,真正的执行逻辑所在 .withIdentity("myJob", "group1") //定义name 和 group .usingJobData("message","hello myJob1") //加入属性到jobDataMap .usingJobData("FloatJobValue",8.88f) //加入属性到jobDataMap .build(); //2.创建一个Trigger触发器的实例,定义该job立即执行,并且每2秒执行一次,一直执行 SimpleTrigger trigger = TriggerBuilder.newTrigger() .withIdentity("myTrigger", "group1") .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()) .build(); //3.创建schedule实例 StdSchedulerFactory factory = new StdSchedulerFactory(); Scheduler scheduler = factory.getScheduler(); scheduler.start(); //启动 scheduler.scheduleJob(jobDetail,trigger); // jobDetail和trigger加入调度 } }
案例:
需求:假设你正在开发一个在线学习平台,需要实现以下定时任务:
每天凌晨1点,统计当天新增用户数量,并发送邮件通知管理员。 每周一凌晨2点,计算上一周的学习活跃用户,将活跃用户信息保存到数据库。
- 实现job逻辑
java
代码解读
复制代码
@Component public class ActiveUserStatsJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { // 在这里编写计算活跃用户信息的逻辑 System.out.println("计算学习活跃用户并保存到数据库..."); } }
java
代码解读
复制代码
@Component public class NewUserStatsJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 在这里编写统计新增用户的逻辑 System.out.println("统计新增用户数量并发送邮件通知管理员..."); } }
- 配置触发器和调度器
scss
代码解读
复制代码
/** * quartz配置类 * 注意: 添加后运行程序即可quartz自动运行 * @version 1.0.0 * @date 2023/8/3 */ @Configuration public class QuartzConfig { @Bean public JobDetail newUserStatsJobDetail() { return newJob(NewUserStatsJob.class) .withIdentity("newUserStatsJob") .storeDurably() .build(); } @Bean public Trigger newUserStatsJobTrigger() { return newTrigger() .forJob(newUserStatsJobDetail()) .withIdentity("newUserStatsJobTrigger") // .withSchedule(cronSchedule("0 0 1 * * ?")) // 每天凌晨1点执行 .withSchedule(cronSchedule("0 0/3 * * * ?")) // 3分钟 .build(); } @Bean public JobDetail activeUserStatsJobDetail() { return newJob(ActiveUserStatsJob.class) .withIdentity("activeUserStatsJob") .storeDurably() .build(); } @Bean public Trigger activeUserStatsJobTrigger() { return newTrigger() .forJob(activeUserStatsJobDetail()) .withIdentity("activeUserStatsJobTrigger") // .withSchedule(cronSchedule("0 0 2 * * MON")) // 每周一凌晨2点执行 .withSchedule(cronSchedule("0 0/2 * * * ?")) // 两分钟执行 .build(); } }
常见时间(corn语法)
arduino
代码解读
复制代码
"30 * * * * ?" 每半分钟触发任务 "30 10 * * * ?" 每小时的10分30秒触发任务 "30 10 1 * * ?" 每天1点10分30秒触发任务 "30 10 1 20 * ?" 每月20号1点10分30秒触发任务 "30 10 1 20 10 ? *" 每年10月20号1点10分30秒触发任务 "30 10 1 20 10 ? 2011" 2011年10月20号1点10分30秒触发任务 "30 10 1 ? 10 * 2011" 2011年10月每天1点10分30秒触发任务 "30 10 1 ? 10 SUN 2011" 2011年10月每周日1点10分30秒触发任务 "15,30,45 * * * * ?" 每15秒,30秒,45秒时触发任务
相比spring自带的定时触发器的好处
spring自带的定时触发器,如springtask
Spring task 优点:无需整合spring,作业类中就可以调用业务service 缺点:单线程;不能做数据存储型的定时任务,不能定时到年月日时分秒 Quartz 优点:多线程;可以做数据存储型的定时任务,维护性高; 缺点:需要整合spring,不能直接调用业务层service;