背景:最近公司一个需求用到定时任务进行采集操作,故写文章来记录一下定时任务的基本概念
一、什么是Quartz
quartz是一个定时调度的框架,指定时间内触发执行某个动作;它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中。
二、为什么使用Quartz
1、为什么要用定时任务
1)无需手动触发 :无需页面(人工)触发动作;
2)执行时间准确:会在准确的时间内进行业务处理;
3)低耦合:单独为一个动作体,可以自行开关,不影响其他业务功能;
2、为什么使用Quartz
1)目前公司使用较多的定时任务框架为xxl-Job,elastic-Job,此框架都是基于Quartz进行二次开发;
2)有些传统互联网公司定时任务框架还是使用Quartz
三、常见开源定时任务的框架的异同
四、Quartz的组件
1)Scheduler(调度器):Scheduler 是 Quartz 的核心组件,它负责管理和调度所有的任务。Scheduler 可以启动、停止、暂停和恢复任务的执行,还可以配置任务的触发条件和执行计划。
2)Job(任务):Job 是需要被调度执行的实际任务。您可以定义自己的 Job 类,实现自己的业务逻辑,并将其注册到 Scheduler 中。Quartz 提供了不同类型的 Job,如无状态的 Job、有状态的 Job 等,以满足不同的需求。
3)Trigger(触发器):Trigger 负责定义任务的触发条件,即何时触发任务的执行。您可以为每个 Job 关联一个或多个 Trigger,根据时间表达式(如 Cron 表达式)或者特定的时间间隔来配置触发器。
4)JobDetail(任务详情):JobDetail 是与 Job 相关联的详细信息,包括 Job 的名称、所属的 Job 类、Job 的身份标识等。每个 Job 都有一个对应的 JobDetail。
5)JobStore(任务存储):JobStore 是 Quartz 的持久化机制,负责将任务和调度相关的信息存储到数据库或其他存储服务器托管网介质中。这样即使应用程序重启或者服务器关闭,已经配置的调度任务仍然可以得到保留。
6)Listener(监听器):Quartz 提供了丰富的监听器接口,让您可以监控任务的状态变化、执行情况以及异常事件。通过实现 Quartz 的监听器接口,您可以在任务执行前后、暂停和恢复、出现错误等情况下执行额外的逻辑。
7)ThreadPool(线程池):Scheduler 使用线程池来并发执行任务,提高任务的处理效率。Quartz 允许您配置线程池的大小、类型和特性,以适应不同的负载情况。
三大核心组件:
1)任务Job:即想要调用的任务类,需要实现org.quartz.job接口,并重写execute()方法,任务调度时会执行execute()方法。(最新版本实现QuartzJobBean类,重写executeInternal方法)
2)触发器Trigger:即执行任务的触发器,当满足什么条件时会去执行你的任务Job,主要分为根据时长间隔执行的SimpleTrigger和根据日历执行的CronTrigger。
3)调度器Scheduler:即将Trigger和Job绑定之后,根据Trigger中的设定,负责进行Job调度的组件。
五、Quartz持久化
1、为什么要持久化?
当程序突然被中断时,如断电,内存超出时,很有可能造成任务的丢失。可以将调度信息存储到数据库里面,进行持久化,当程序被中断后,再次启动,仍然会保留中断之前的数据,继续执服务器托管网行,而并不是重新开始。
2、Quartz提供了两种持久化方式
Quartz提供两种基本作业存储类型:
1)RAMJobStore
在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。2)JobStoreTX (分布式方式一般采用此种方式,持久化到数据库中)
所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务。
六、Quartz单实例的入门(大致流程,详细细节可以查看官网)
1、引入pom
org.springframework.boot
spring-boot-starter-quartz
2、定义Job
只需要继承QuartzJobBean,并重载executeInternal方法即可定义你自己的Job执行逻辑
@Slf4j
public class HelloJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
// get parameters
context.getJobDetail().getJobDataMap().forEach(
(k, v) -> log.info("param, key:{}, value:{}", k, v)
);
// your logics
log.info("Hello Job执行时间: " + new Date());
}
}
3、配置Job
JobDetail, Trigger, Schedule(这里采用CronScheduleBuilder)
/**
* @author pdai
*/
@Configuration
public class QuartzConfig {
@Bean("helloJob")
public JobDetail helloJobDetail() {
return JobBuilder.newJob(HelloJob.class)
.withIdentity("DateTimeJob")
.usingJobData("msg", "Hello Quartz")
.storeDurably()//即使没有Trigger关联时,也不需要删除该JobDetail
.build();
}
@Bean
public Trigger printTimeJobTrigger() {
// 每秒执行一次
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
return TriggerBuilder.newTrigger()
.forJob(helloJobDetail())
.withIdentity("quartzTaskService")
.withSchedule(cronScheduleBuilder)
.build();
}
}
4、测试定时任务
ps:Quartz分布式案例进入下方借鉴文章查看
七、开源引擎框架与业务如何结合使用
总结:
常见引擎框架:定时任务引擎quartz、规则引擎drools、流程引擎acitiviti等与业务结合的时候,需要在指定的步骤中对业务表进行操作,就可以实现将所需要的信息存入到业务表中,后续把相应的业务表信息与引擎表信息关联就可。例如下方是定时任务执行的类(需要继承QuartzJobBean),此类中就可以进行业务的操作。
/**
* @date 2023/7/11
* 定时任务实现类
*/
@Slf4j
public class DataHandler extends QuartzJobBean {
@Autowired
private IDataLogService dataLogService;
// 定时任务执行的类
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
// 1、context对象可以获取任务id等信息
// 2、业务操作(比如操作业务表,进行采集任务后,再次更新业务表的采集状态)
dataLogService.update();
...
}
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net