定时框架Quartz

Quartz 三要素

quartz [kwɔːts] 石英

调度器(Scheduler) :所有的任务都是从这里开始。

触发器(Trigger) :定义任务执行的方式、间隔。

任务(JobDetail & Job ) :定义任务具体执行的逻辑。

Scheduler

scheduler 是quartz的核心所在,所有的任务都是通过scheduler开始。
scheduler是一个接口类,所有的具体实现类都是通过SchedulerFactory工厂类实现,但是SchedulerFactory有两个具体的实现类,如图:

在这里插入图片描述

1.StdSchedulerFactory默认值加载是当前工作目录下的”quartz.properties”属性文件。如果加载失败,会去加载org/quartz包下的”quartz.properties”属性文件。一般使用这个实现类就能满足我们的要求。
2.DirectSchedulerFactory:这个我也没用过QAQ,听说是为那些想绝对控制 Scheduler 实例是如何生产出的人所设计的。

Trigger

惊奇的发现trigger采用的也是buidler模式-。-(想了解什么事builder模式可以看下我的另外一篇博客https://blog.csdn.net/bicheng4769/article/details/80988996)
这里我只给大家介绍一些常用的方法,其余的可以自己查看文档:

withIdentity()                给触发器一些属性 比如名字,组名。
startNow()                 立刻启动
withSchedule(ScheduleBuilder schedBuilder) 以某种触发器触发。
usingJobData(String dataKey, Boolean value) 给具体job传递参数。

Trigger的重点内容就是在withSchedule这个方法,从参数开始:查看SchedulerBuilder,这个是个抽象类,一共有4种具体实现方法,如图:

在这里插入图片描述

SimpleScheduleBuilder

最简单的触发器,表示从某一时刻开始,以一定的时间间隔执行任务。
属性:
repeatInterval 重复间隔。
repeatCount 重复次数。
比如:现在开始,以后每一个小时执行一次。

Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInHours(1)
                .repeatForever()).build();

CronScheduleBuilder
cron表达式。

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                //加入 scheduler之后立刻执行
                .startNow()
                //定时 ,每个1秒钟执行一次
                .withSchedule(cronSchedule("0 0/2 8-17 * * ?") // 每天8:00-17:00,每隔2分钟执行一次
                        ).build();

JobDetail & Job

jobdetail 就是对job的定义,而job是具体执行的逻辑内容。
具体的执行的逻辑需要实现 job类,并实现execute方法。

为什么设计成JobDetail + Job,不直接使用Job?

JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。
这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

如何禁止并发执行?

项目中出现了一种情况,本来job执行时间只需要10s,但是由于数据库量增大之后,执行时间变成了60s,而我设置的间隔时间是30s,这样就会出现上次任务还没执行完成,下次任务就开始执行了。所以,在这种情况下,我们要禁止quart的并发操作。

方式1:

spring中将job的concurrent属性设置为false。默认是true 如下:

     <bean id="scheduleJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="scheduleBusinessObject"/>
        <property name="targetMethod" value="doIt"/>
        <property name="concurrent" value="false"/>
    </bean>

方式2:
job类上加上注解@DisallowConcurrentExecution。

@DisallowConcurrentExecution
public class HelloQuartz implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        JobDetail detail = jobExecutionContext.getJobDetail();
        String name = detail.getJobDataMap().getString("name");
        System.out.println("my job name is  " + name + " at " + new Date());

    }
}

注意:@DisallowConcurrentExecution是对JobDetail实例生效,如果一个job类被不同的jobdetail引用,这样是可以并发执行。

原文链接:https://blog.csdn.net/bicheng4769/article/details/81097305

cron表达式详解

在这里插入图片描述

https://www.cnblogs.com/yanghj010/p/10875151.html

Quartz的几个核心概念如下:

Job:代表一个工作,要执行的内容,此接口只有一个方法execute().

JobDetail:代表一个可执行的调度程序,Job是这个可执行调度程序的内容,另外,JobDetail还包含了这个任务调度的方案和策略。

Trigger:代表一个调度参数的配置

Scheduler:代表一个调度容器,可以注册多个JobDetial和Trigger

SchedulerFactory:代表一个调度工厂,用来创建一个scheduler调度器

Quartz执行流程:体现在Spring就是,Job注入到JobDetial,JobDetial注入到Trigger,Trigger注入到Scheduler中

动态配置的调度时间:

https://www.cnblogs.com/laoyeye/p/9352002.html

maven依赖(quartz版本2.2.1)

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.2.1</version>
</dependency>

简单实例

主函数

/**
 * @(#)quartzMain.java, 2020/7/13.
 * <p/>
 * Copyright 2020 Netease, Inc. All rights reserved.
 * NETEASE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package quartz.myQuartz;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

/**
 * @author lvhouhou(lvhouhou @ 163.com)
 */
public class quartzMain {
    public static void main(String[] args) {
        //定义一个JobDetail
        JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class)
                //定义name和group
                .withIdentity("job1", "group1")
                //job需要传递的内容
                .usingJobData("name", "sdas")
                .build();
        //定义一个Trigger
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                //加入 scheduler之后立刻执行
                .startNow()
                //定时 ,每个1秒钟执行一次
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1)
                        //重复执行
                        .repeatForever()).build();
        try {
            //创建scheduler
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start(); //运行一段时间后关闭
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            scheduler.shutdown();
        } catch (
                SchedulerException e) {
            e.printStackTrace();
        }
    }

}

HelloQuartz 类

/**
 * @(#)HelloQuartz.java, 2020/7/13.
 * <p/>
 * Copyright 2020 Netease, Inc. All rights reserved.
 * NETEASE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package quartz.myQuartz;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;

import java.util.Date;

/**
 * @author lvhouhou(lvhouhou @ 163.com)
 */
public class HelloQuartz implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        JobDetail detail = jobExecutionContext.getJobDetail();
        String name = detail.getJobDataMap().getString("name");
        System.out.println("my job name is  " + name + " at " + new Date());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值