Quartz开源作业调度框架原理及使用Quartz实现定时订单测试

Stella981
• 阅读 743

Quartz

Quartz 是 OpenSymphony 开源组织在 Job scheduling 领域又一个开源项目,它可以与 J2EE 与 J2SE 应用程序相结合也可以单独使用。Quartz 可以用来创建简单或为运行十个,百个,甚至是好几万个 Jobs 这样复杂的程序。Jobs 可以做成标准的 Java 组件或 EJBs。Quartz 的最新版本为 Quartz 2.3.0。

1.1 Quartz 调用流程

Quartz开源作业调度框架原理及使用Quartz实现定时订单测试

  • JOB: 定义自己的任务
  • JobDetail: 封装 JOB 对象的
  • 调度器: 管理全部的任务(Scheduler)
  • 触发器: 开启新的线程执行任务(jobDetail)

1.2 Quartz组件说明

1.2.1 Scheduler -- 调度器

     Scheduler 被用来对 Trigger 和 Job 进行管理。Trigger 和 JobDetail 可以注册到Scheduler 中,两者在 Scheduler 中都拥有自己的唯一的组和名称用来进行彼此的区分,Scheduler 可以通过组名或者名称来对 Trigger 和 JobDetail 来进行管理。一个 Trigger只能对应一个 Job,但是一个 Job 可以对应多个 Trigger。每个 Scheduler 都包含一个SchedulerContext,用来保存 Scheduler 的上下文。Job 和 Trigger 都可以获取SchedulerContext 中的信息。

     Scheduler 包含两个重要的组件,JobStore 和 ThreadPool。JobStore 用来存储运行时信息,包括 Trigger,Schduler,JobDetail,业务锁等。它有多种实现 RAMJob(内存实现),JobStoreTX(JDBC,事务由 Quartz 管理)等。ThreadPool 就是线程池,Quartz有自己的线程池实现。所有任务的都会由线程池执行。

     Scheduler 是由 SchdulerFactory 创建,它有两个实现:DirectSchedulerFactory和 StdSchdulerFactory。前者可以用来在代码里定制你自己的 Schduler 参数。后者是直接读取 classpath 下的 quartz.properties(不存在就都使用默认值)配置来实例化Schduler。通常来讲,我们使用 StdSchdulerFactory 也就足够了。

1.2.2 Trigger -- 触发器

     Trigger 是用来定义 Job 的执行规则,主要有四种触发器,其中 SimpleTrigger 和CronTrigger 触发器用的最多。
     SimpleTrigger:从某一个时间开始,以一定的时间间隔来执行任务。它主要有两个属性,repeatInterval 重复的时间间隔;repeatCount 重复的次数,实际上执行的次数是 n+1,因为在 startTime 的时候会执行一次。
     CronTrigger:适合于复杂的任务,使用 cron 表达式来定义执行规则。
     CalendarIntervalTrigger:类似于 SimpleTrigger,指定从某一个时间开始,以一定的时间间隔执行的任务。 但是 CalendarIntervalTrigger 执行任务的时间间隔比SimpleTrigger 要丰富,它支持的间隔单位有秒,分钟,小时,天,月,年,星期。
相较于 SimpleTrigger 有两个优势:

  • 1、更方便,比如每隔 1 小时执行,你不用自己去计算 1小时等于多少毫秒。
  • 2、支持不是固定长度的间隔,比如间隔为月和年。但劣势是精度只能到秒。它的主要两个属性,_interval执行间隔_;_intervalUnit 执行间隔的单位_(秒,分钟,小时,天,月,年,星期)。

     DailyTimeIntervalTrigger:指定每天的某个时间段内,以一定的时间间隔执行任务。并且它可以支持指定星期。它适合的任务类似于:指定每天 9:00 至 18:00 ,每隔70 秒执行一次,并且只要周一至周五执行。它的属性有

  • startTimeOfDay 每天开始时间;
  • endTimeOfDay 每天结束时间;
  • daysOfWeek 需要执行的星期;
  • interval 执行间隔;
  • intervalUnit 执行间隔的单位(秒,分钟,小时,天,月,年,星期);
  • repeatCount 重复次数*。

     所有的 trigger 都包含了 StartTime 和 endTIme 这两个属性,用来指定 Trigger被触发的时间区间。

     所有的 trigger 都可以设置 MisFire 策略,该策略是对于由于系统奔溃或者任务时间过长等因导致trigger在应该触发的时间点没有触发,并且超过了misfireThreshold设置的时间(默认是一分钟,没有超过就立即执行)就算 misfire 了,这个时候就该设置如何应对这种变化了。激活失败指令(Misfire Instructions)是触发器的一个重要属性,它指定了 misfire 发生时调度器应当如何处理。所有类型的触发器都有一个默认的指令,叫做Trigger.MISFIRE_INSTRUCTION_SMART_POLICY,但是这个这个“聪明策略”对于不同类型的触发器其具体行为是不同的。对于 SimpleTrigger,这个“聪明策略”将根据触发器实例的状态和配置来决定其行。

1.2.3 SimpleTrigger 常见策略:

  • MISFIRE_INSTRUCTION_FIRE_NOW 立刻执行。对于不会重复执行的任务,这是默认的处理策略。
  • MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT 在下一个激活点执行,且超时期内错过的执行机会作废。
  • MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_COUNT 立即执行,且超时期内错过的执行机会作废。
  • MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT 在下一个激活点执行,并重复到指定的次数。
  • MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_COUNT 立即执行,并重复到指定的次数。
  • MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 忽略所有的超时状态,按照触发器的策略执行。

对于 CronTrigger,该“聪明策略”默认选择 MISFIRE_INSTRUCTION_FIRE_ONCE_NOW以指导其行为。

1.2.4 CronTrigger 常见策略:

  • MISFIRE_INSTRUCTION_FIRE_ONCE_NOW 立刻执行一次,然后就按照正常的计划执行。
  • MISFIRE_INSTRUCTION_DO_NOTHING 目前不执行,然后就按照正常的计划执行。这意味着如果下次执行时间超过了 end time,实际上就没有执行机会了。

1.2.5 Job

     Job 是 一 个 任 务 接 口 , 开 发 者 定 义 自 己 的 任 务 须 实 现 该 接 口 实 现 void execute(JobExecutionContext context)方法,JobExecutionContext 中提供了调度上下文的各种信息。Job 中的任务有可能并发执行,例如任务的执行时间过长,而每次触发的时间间隔太短,则会导致任务会被并发执行。如果是并发执行,就需要一个数据库锁去避免一个数据被多次处理。可以 execute ()方法上添加注解@DisallowConcurrentExecution 解决这个问题。

1.2.6 JobDetail

     Quartz 在每次执行 Job 时,都重新创建一个 Job 实例,所以它不直接接受一个 Job的实例,相反它接收一个 Job 实现类,以便运行时通过 newInstance()的反射机制实例化Job。因此需要通过一个类来描述 Job 的实现类及其它相关的静态信息,如 Job 名字、描述、关联监听器等信息,JobDetail 承担了这一角色。所以说 JobDetail 是任务的定义,而 Job是任务的执行逻辑。

1.2.7 Calendar

     Calendar:org.quartz.Calendar 和 java.util.Calendar 不同,它是一些日历特定时间点的集合(可以简单地将 org.quartz.Calendar 看作 java.util.Calendar 的集合——java.util.Calendar 代表一个日历时间点,无特殊说明后面的 Calendar 即指org.quartz.Calendar)。一个 Trigger 可以和多个 Calendar 关联,以便排除或包含某些时间点。

1.3 SpringBoot整合Quartz -- 实现订单超时任务

业务需求:

  • 说明:当订单创建之后,如果长时间不支付.则订单会超时.
  • 条件: status=1 未支付. status=6 交易关闭.
  • 规定: 30 分钟超时.

1.3.1 导入jar包

<!--添加 Quartz 的支持 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

1.3.2 编辑配置类

@Configuration    //标识配置类
public class OrderQuartzConfig {
    
    //定义任务详情
    @Bean
    public JobDetail orderjobDetail() {
        //指定job的名称和持久化保存任务
        return JobBuilder
                .newJob(OrderQuartz.class)    //引入自己的job
                .withIdentity("orderQuartz")  //定义任务名称
                .storeDurably()
                .build();
    }
    //定义触发器
    @Bean
    public Trigger orderTrigger() {
        /*SimpleScheduleBuilder builder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInMinutes(1)    //定义时间周期
                .repeatForever();*/
        //定义调度器
        //"0 0/1 * * * ?"   表示每隔1分钟执行一次
        CronScheduleBuilder scheduleBuilder 
            = CronScheduleBuilder.cronSchedule("0 0/1 * * * ?");
        return TriggerBuilder
                .newTrigger()
                .forJob(orderjobDetail())
                .withIdentity("orderQuartz")
                .withSchedule(scheduleBuilder).build();
    }
}

1.3.3 定义任务 -- OrderQuartz

//准备订单定时任务
@Component
public class OrderQuartz extends QuartzJobBean{
    
    //修改数据库的超时订单的
    @Autowired
    private OrderMapper orderMapper;
    
    /**
     * 条件:30分钟超时    1改为6
     *判断依据:    创建订单的时间    now-created>30分钟
     *            created<now-30
     *sql: update tb_order set status=6,updated=#{date}
     *        where created <#{timeOut} and status=1;
     */
    @Override
    @Transactional
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        //java中专门操作时间的api
        Calendar calendar = Calendar.getInstance(); //获取当前时间
        //field操作的时间属性 分钟 小时  年 月等
        calendar.add(Calendar.MINUTE, -30);
        //获取计算之后的时间
        Date timeOut = calendar.getTime();
        
        /**
        * entity: 要修改的数据 挑选其中不为 null 的元素当 set 条件
        * updateWrapper: 条件构造器
        */
        Order order = new Order();
        order.setStatus(6)
             .setUpdated(new Date());
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("status", 1)
                     .lt("created", timeOut);
        orderMapper.update(order, updateWrapper);
        System.out.println("定时任务完成!!!!!");
    }
    
    
    
}

源于老师所教的笔记总结,定时任务完成,文章到此也就结束了,谢谢!!!

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Nginx + lua +[memcached,redis]
精品案例1、Nginxluamemcached,redis实现网站灰度发布2、分库分表/基于Leaf组件实现的全球唯一ID(非UUID)3、Redis独立数据监控,实现订单超时操作/MQ死信操作SelectPollEpollReactor模型4、分布式任务调试Quartz应用
Easter79 Easter79
3年前
SpringBoot2.0高级案例(06):整合 QuartJob ,实现定时器实时管理
一、QuartJob简介1、一句话描述Quartz是一个完全由java编写的开源作业调度框架,形式简易,功能强大。2、核心API(1)、Scheduler代表一个Quartz的独立运行容器,Scheduler将Trigger绑定到特定JobDetail,这样当Tri
Stella981 Stella981
3年前
SpringBoot2.0高级案例(06):整合 QuartJob ,实现定时器实时管理
一、QuartJob简介1、一句话描述Quartz是一个完全由java编写的开源作业调度框架,形式简易,功能强大。2、核心API(1)、Scheduler代表一个Quartz的独立运行容器,Scheduler将Trigger绑定到特定JobDetail,这样当Tri
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
京东云开发者 京东云开发者
11个月前
Quartz核心原理之架构及基本元素介绍 | 京东物流技术团队
1什么是QuartzQuartz是一个作业调度框架,它可以与J2EE和J2SE应用相结合,也可以单独使用。它能够创建多个甚至数万个jobs这样复杂的程序,jobs可以做成标准的java组件或EJBS。Quartz很容易上手,创建一个任务仅需实现Job接口,
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这