【一】Quartz定时任务

Quartz定时任务

一、认识Quartz

如果对定时任务没有分布式需求,但需要对任务有一定的动态管理,例如任务的启动、暂停、恢复、停止和触发时间修改,那么Quartz非常适合。

Quartz是Java定时任务领域一个非常优秀的框架,由OpenSymphony(一个开源组织)开发,这个框架进行了优良地解耦设计,整个模块可以分为三大部分:

Job:顾名思义,指待定时执行的具体工作内容;
Trigger:触发器,指定运行参数,包括运行次数、运行开始时间和技术时间、运行时长等;
Scheduler:调度器,将Job和Trigger组装起来,使定时任务被真正执行;

以上三者的关系为:

  • 一个JobDetail(Job的实现类)可以绑定多个Trigger,但一个Trigger只能绑定一个JobDetail;
  • 每个JobDetail和Trigger通过group和name来标识唯一性;
  • 一个Scheduler可以调度多组JobDetail和Trigger。

【一】Quartz定时任务_第1张图片

可以将Scheduler、JobDetail、Trigger三者理解为一个工厂车间管理:
JobDetail:比作一个生产车间,例如:手机、电脑等;
Trigger: 比作为生产车间的生产线,每个车间可以同又多个生产线同时生产同一个物品;
Scheduler: 比作对车间主任,对生产车间的管理,指挥车间内的任务调度;

二、基本使用

基于SpringBoot对Quartz使用

2.1 导入依赖包

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-quartzartifactId>
dependency>

2.2 创建Job工作任务


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()));
    }
}

2.3.1 创建Scheduler和Trigger,执行定时任务:

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();

    }
}

2.3.2 结果展示

【一】Quartz定时任务_第2张图片

2.4.1 基于Cron表达式的定时任务

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();

    }

2.4.2 结果展示

【一】Quartz定时任务_第3张图片

三、关于Quartz涉及到的类之间的关系如下图所示

【一】Quartz定时任务_第4张图片

  • JobDetail:Job接口的实现类,由JobBuilder将具体定义任务的类包装而成。
  • Trigger:触发器,定义定时任务的触发规则,包括执行间隔、时长等,使用TriggerBuilder创建,JobDetail和Trigger可以一对多,反之不可。触发器可以拥有多种状态。
  • Scheduler:调度器,将Job和Trigger组装起来,使定时任务被真正执行;是Quartz的核心,提供了大量API。
  • JobDataMap:集成Map,通过键值对为JobDetail存储一些额外信息。(在后期使用db数据库的时候可以将任务信息放进去)
  • JobStore:用来存储任务和触发器相关的信息,例如任务名称、数量、状态等等。Quartz 中有两种存储任务的方式,一种在在内存(RAMJobStore),一种是在数据库(JDBCJobStore)。

3.1 Job

Job是一个接口,只有一个方法execute(),我们创建具体的任务类时要继承Job并重写execute()方法,使用JobBuilder将具体任务类包装成一个JobDetail(使用了建造者模式)交给Scheduler管理。每个JobDetail由name和group作为其唯一身份标识。

JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据。
JobDataMap继承Map,可通过键值对为JobDetail存储一些额外信息。

3.2 Trigger

Trigger有四类实现,分别如下:

SimpleTrigger:简单触发器,支持定义任务执行的间隔时间,执行次数的规则有两种,一是定义重复次数,二是定义开始时间和结束时间。如果同时设置了结束时间与重复次数,先结束的会覆盖后结束的,以先结束的为准。
CronTrigger:基于Cron表达式的触发器。
CalendarIntervalTrigger:基于日历的触发器,比简单触发器更多时间单位,且能智能区分大小月和平闰年。
DailyTimeIntervalTrigger:基于日期的触发器,如每天的某个时间段。
Trigger是有状态的:NONE、 NORMAL、 PAUSED、 COMPLETE、 ERROR、 BLOCKED状态之间转换关系:
【一】Quartz定时任务_第5张图片

COMPLETE状态比较特殊,我在实际操作中发现,当Trigger长时间暂停后(具体时长不太确定)再恢复,状态就会变为COMPLETE,这种状态下无法再次启动该触发器。

3.3 Scheduler

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/

你可能感兴趣的:(学习笔记,java)