ElasticJob-01-Quartz梳理

259 阅读4分钟

Quartz基础概念

任务Job

Job就是我们要实现的任务类,每一个Job必须实现org.quartz.job接口,并实现接口定义的execte()方法。

触发器Trigger

Trigger为你执行任务的触发器,如每天下午3点定时发送一个邮件,Trigger将会设置3点进行执行该任务。 Trigger主要包含两种:SimpleTrigger和CronTrigger。

调度器Scheduler

Scheduler为任务的调度器,他会将Job和Trigger整合起来,负责基于Trigger设定的时间来执行Job。

Quartz的体系结构

image.png

代码示例

每10秒执行1次任务

/**
 * 定时任务类
 * @author HigginCui
 * @date 2023/1/30 上午12:08
 */
public class QuartzTestJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println(time+"----当前Quartz任务开始执行");
    }
}
/**
 * 任务调度器
 * @author HigginCui
 * @date 2023/1/30 上午12:09
 */
public class QuartzTestScheduler {

    public static void main(String[] args) throws Exception{

        //获取任务调度的实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        //定义任务调度实例,并与TestJob绑定,("testJob":任务的名称,需要唯一)
        JobDetail jobDetail = JobBuilder
                .newJob(QuartzTestJob.class)
                .withIdentity("testJob","testJobGroup")
                .build();

        //定义触发器,马上执行一次,后面每10S执行一次
        Trigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity("testTrigger","testTriggerGroup")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(10))
                .build();

        //使用触发器来调度任务的执行
        scheduler.scheduleJob(jobDetail,trigger);

        //开始任务
        scheduler.start();

    }
}

关键参数概念解释

Job和JobDetail

  • Job:工作任务调度的接口,任务类需要实现该接口,接口中定义了execute()方法(类似JDK提供的TimeTask的run()方法),在里面编写任务执行的业务逻辑。
  • Job实例在Quartz中的生命周期:在调用execute方法前会创建一个新的job实例,当调用完成后,关联的Job对象实例会被释放,释放的实例会被垃圾回收。
  • JobDetail:为Job实例提供设置属性,以及JobDetailMap成员变量属性,用来存储特定Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例。
JobDetail重要属性:name,group,jobClass,jobDataMap

name(任务名称)------jobDetail.getKey().getName();

group(组名称)------jobDetail.getKey().getGroup()

jobClass(任务类)------jobDetail.getJobClass().getName()

jobDataMap------jobDetail.getJobDataMap()
  • Job和JobDetail的关系

JobExecutionContext

当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法,Job能通过JobExecutionContext来获取Job明细数据和Quartz运行环境信息。

JobDataMap

1.使用Map获取

  • 在进行任务调度时,JobDataMap存储在Job ExecutionContext中。
  • JobDataMap可以用来装载任何可序列化的数据对象,当job实例对象被执行时这些参数会传递给他。
  • JobDataMap实现了JDK的Map接口,并且添加了非常方便的方法来存取基本数据类型。

【任务调度类】

public static void main(String[] args) throws Exception{

    Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

    JobDetail jobDetail = JobBuilder
            .newJob(QuartzTestJob.class)
            .withIdentity("testJob","testJobGroup")
            //这里传递一个上下文信息到jobDetail中
            .usingJobData("externalInfo","jobDetail扩展信息")
            .build();

    Trigger trigger = TriggerBuilder
            .newTrigger()
            .withIdentity("testTrigger","testTriggerGroup")
            .startNow()
            .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(10))
            //这里传递一个上下文信息到trigger中
            .usingJobData("externalInfo","trigger扩展信息")
            .build();

    //使用触发器来调度任务的执行
    scheduler.scheduleJob(jobDetail,trigger);

    //开始任务
    scheduler.start();

}

【任务类】

public class QuartzTestJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println(time+"----当前Quartz任务开始执行");
        System.out.println("jobExecutionContext.getJobDetail().getJobDataMap().get("externalInfo")======="+jobExecutionContext.getJobDetail().getJobDataMap().get("externalInfo"));
        System.out.println("jobExecutionContext.getTrigger().getJobDataMap().get("externalInfo")======="+jobExecutionContext.getTrigger().getJobDataMap().get("externalInfo"));
    }
}

执行结果:

image.png

有状态的Job和无状态的Job

有状态的Job可以理解为多次Job调用期间可以持有一些状态信息,会存储在JobDataMap中,而默认的无状态的Job每次调用都会创建换一个新的DataJobMap。

新增一个注解 @PersistJobDataAfterExecution,就会变成有状态的Job,这样多次调用时,使用的是一个Job实例,即单例的Job。

Trigger

image.png

Quartz有不同类型的触发器,用的最多的是SimpleTrigger和CronTrigger。

Simple触发器

最为简单的一种触发器,使用在特定日期/时间启动,并且可以间隔重复执行n次的Job所设计的。 Simple触发器设置的关键参数:开始时间、结束时间、重复次数、时间间隔。

【代码示例】

//定义触发器,指定时间开始执行,后面每10S执行一次,执行3次
Trigger trigger = TriggerBuilder
        .newTrigger()
        .withIdentity("testTrigger","testTriggerGroup")
        //什么时候开始执行
        .startAt(new Date()) 
        //每10s执行一次,执行3次(注:这里从0开始计数)
        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(10).withRepeatCount(2))
        .build();

Cron触发器

基于Cron表达式的调度,更为灵活。