如果对定时任务没有分布式需求,但需要对任务有一定的动态管理,例如任务的启动、暂停、恢复、停止和触发时间修改,那么Quartz非常适合。
Quartz是Java定时任务领域一个非常优秀的框架,由OpenSymphony(一个开源组织)开发,这个框架进行了优良地解耦设计,整个模块可以分为三大部分:
Job:顾名思义,指待定时执行的具体工作内容;
Trigger:触发器,指定运行参数,包括运行次数、运行开始时间和技术时间、运行时长等;
Scheduler:调度器,将Job和Trigger组装起来,使定时任务被真正执行;
以上三者的关系为:
可以将Scheduler、JobDetail、Trigger三者理解为一个工厂车间管理:
JobDetail:比作一个生产车间,例如:手机、电脑等;
Trigger: 比作为生产车间的生产线,每个车间可以同又多个生产线同时生产同一个物品;
Scheduler: 比作对车间主任,对生产车间的管理,指挥车间内的任务调度;
基于SpringBoot对Quartz使用
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-quartzartifactId>
dependency>
package com.mengyb.test.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class QuartzSimpleJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("当前执行的定时任务为----线程:" + Thread.currentThread().getName() + "--" + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
}
}
package com.mengyb.test.task;
import com.mengyb.test.quartz.QuartzSimpleJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.concurrent.TimeUnit;
public class QuartzTask {
public static void main(String[] args) throws SchedulerException, InterruptedException {
// 1、首先创建调度器
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
// 2、创建JobDetail实例,并与SimpleJob类绑定(Job执行内容)
JobDetail jobDetail = JobBuilder.newJob(QuartzSimpleJob.class) //加载任务类 完成与QuartzSimpleJob的绑定 要求 QuartzSimpleJob 必须实现Job接口
// 参数1 任务的名称 参数二 任务组的名称
.usingJobData("jobId1", "JobTestGroup")
.build();
// 3、构建触发器Trigger 定义执行频率和时长
SimpleTrigger trigger = TriggerBuilder.newTrigger()
// 参数一:触发器的名称 参数二: 触发器组的名称
.withIdentity("triggerKey1", "triggerGroup")
//马上启动触发器
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
// 每个两秒执行一次
.withIntervalInSeconds(5)
// 永久生效
.repeatForever())
.build();
// 4、将JobDetail实例 和 Trigger 触发器 同时交给Scheduler 进行管理
scheduler.scheduleJob(jobDetail, trigger);
// 5、启动Scheduler
scheduler.start();
// 休眠,决定调度器运行时间,这里设置30s
TimeUnit.SECONDS.sleep(30);
// 6、关闭Scheduler
scheduler.shutdown();
}
}
public static void main(String[] args) throws SchedulerException, InterruptedException {
// 1、首先创建调度器
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
// 2、创建JobDetail实例,并与SimpleJob类绑定(Job执行内容)
JobDetail jobDetail = JobBuilder.newJob(QuartzSimpleJob.class) //加载任务类 完成与QuartzSimpleJob的绑定 要求 QuartzSimpleJob 必须实现Job接口
// 参数1 任务的名称 参数二 任务组的名称
.usingJobData("jobId1", "JobTestGroup")
.build();
// 3、构建触发器Trigger 定义执行频率和时长
CronTrigger trigger = TriggerBuilder.newTrigger()
// 参数一:触发器的名称 参数二: 触发器组的名称
.withIdentity("triggerKey1", "triggerGroup")
//马上启动触发器
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
// 4、将JobDetail实例 和 Trigger 触发器 同时交给Scheduler 进行管理
scheduler.scheduleJob(jobDetail, trigger);
// 5、启动Scheduler
scheduler.start();
// 休眠,决定调度器运行时间,这里设置30s
TimeUnit.SECONDS.sleep(30);
// 6、关闭Scheduler
scheduler.shutdown();
}
Job是一个接口,只有一个方法execute(),我们创建具体的任务类时要继承Job并重写execute()方法,使用JobBuilder将具体任务类包装成一个JobDetail(使用了建造者模式)交给Scheduler管理。每个JobDetail由name和group作为其唯一身份标识。
JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据。
JobDataMap继承Map,可通过键值对为JobDetail存储一些额外信息。
Trigger有四类实现,分别如下:
SimpleTrigger:简单触发器,支持定义任务执行的间隔时间,执行次数的规则有两种,一是定义重复次数,二是定义开始时间和结束时间。如果同时设置了结束时间与重复次数,先结束的会覆盖后结束的,以先结束的为准。
CronTrigger:基于Cron表达式的触发器。
CalendarIntervalTrigger:基于日历的触发器,比简单触发器更多时间单位,且能智能区分大小月和平闰年。
DailyTimeIntervalTrigger:基于日期的触发器,如每天的某个时间段。
Trigger是有状态的:NONE、 NORMAL、 PAUSED、 COMPLETE、 ERROR、 BLOCKED状态之间转换关系:
COMPLETE状态比较特殊,我在实际操作中发现,当Trigger长时间暂停后(具体时长不太确定)再恢复,状态就会变为COMPLETE,这种状态下无法再次启动该触发器。
Scheduler调度器,是 **Quartz **的指挥官,由 StdSchedulerFactory 产生,它是单例的。Scheduler中提供了 Quartz 中最重要的 API,默认是实现类是 StdScheduler。
Scheduler中主要的API大概分为三种:
1.操作Scheduler本身:例如start、shutdown等;
2.操作Job,例如:addJob、pauseJob、pauseJobs、resumeJob、resumeJobs、getJobKeys、getJobDetail等
3.操作Trigger,例如pauseTrigger、resumeTrigger等
总结:
定时任务在开发过程中遇到的是很多的,同样也有很多的方式同样可以完成定时任务,之前都是在项目中使用注解**@Scheduled()注解以及cron表达式详解**,但是这样比较死板,很多时候需要停止一些定时任务就需要对代码进行修改,这样是一个很不友好的操作。但Quattz的相遇,可以使用图形化界面进行管理定时任务,使得对项目中的定时任务管理更加的便捷,切操作更加的方便。
以上仅是对Quartz的简单运用,并未涉及到db。
资料:
官网: http://www.quartz-scheduler.org/