Quartz定时任务调度框架从入门到掌握--持续更新

1.Quartz简介

Quartz是一个企业任务日程调度管理组件,无论是互联网公司还是传统的软件行业都是必不可少的,Quartz是好多优秀的定时任务开源框架的基础,很有必要去掌握,只需要掌握少量参数,就可以掌握企业中的定时任务处理。

2.Quartz概念

Quartz是OpenSymphony开源组织在Job scheduling领域的一个开源项目,它可以与J2EE和J2SE应用程序结合也可以单独使用,Quartz是开源且具有丰富特性的“任务调度库”,能够集成于任何的java应用,小到独立的应用,大到电子商业系统,quartz能够创建简单或复杂的任务调度,以执行上十,上百,甚至上万的任务,任务job被定义为标准的java组件,能够执行任何你想要实现的功能,quartz调度框架包含许多企业级的特性,如JTA事物,集群的支持,简而言之,quartz就是基于java实现的任务调度框架,用于执行你想执行的任何任务
官网:
http://www.quartz-scheduler.org/

3.Quartz运行环境

  • Quartz可以运行嵌入在另一个独立式应用程序
  • Quartz可以在应用程序服务器(或servlet容器)内被实例化,并且参与事务
  • Quartz可以作为一个独立的程序运行(其自己的java虚拟机内),可以通过RMI使用
  • Quartz可以被实例化,作为独立的项目集群(负载均衡和故障转移功能),用于作业的执行

4.Quartz的设计模式

  • Builder模式
  • Factory模式
  • 组件模式
  • 链式编程

5.Quartz核心概念

  • 任务job
    job就是你想要实现的任务类,每一个job必须实现org,quartz.job接口,且只需实现接口定义的execute(方法)
  • 触发器Trigger
    Trigger为你执行任务的触发器,比如你每天定时3点发送一份统计邮件,Trigger将会设置3点进行执行该任务。Trigger主要包含两种Simple Trigger和Cron Trigger两种,关于二者的区别的使用场景,后续的课程会进行讨论。
  • 调度器Scheduler
    Scheduler为任务的调度器,它会将任务job及触发器Trigger整合起来,负责基于Trigger设定的时间来执行job

6.Quartz的体系结构

在这里插入图片描述

7.Quartz的几个常用API

以下是Quartz编程API几个重要接口,也是Quartz的重要组件

  • Scheduler 用于与调度程序交互的主程序接口
    Scheduler调度程序-任务执行计划表,只有安排进执行计划的任务job(通过scheduler.schedulerjob方法安排进执行计划),当它预先定义的执行时间到了的时候(任务触发trigger),该任务才会执行。
  • Job 我们预先定义的希望在未来时间内被调度程序执行的任务类,我们可以自定义。
  • JobDetail 使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建的。
  • JobDataMap 可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据,JobDataMap是java Map接口的一个实现,额外增加了一些便于存取基本类型的数据方法。
  • Trigger触发器 Trigger对象是用来触发执行job的,当调度一个job时,我们实例一个触发器然后调度它的属性来满足job执行的条件。表明任务在什么时候会执行,定义了一个已经被安排的任务将会在什么时候执行的时间条件,比如每2秒就执行一次
  • JobBuilder 用于声明一个任务实例,也可以定义关于该任务的详情比如任务名、组件等,这个声明的实例将会作为一个实际执行的任务。
  • TriggerBuilder 触发器创建器,用于创建触发器trigger实例。
  • JobListener、TriggerListener、SchedulerListenner监听器,用于对组件的监听
7.1 Job和JobDetail介绍
  • Job :工作任务调度的接口,任务类需要实现该接口,该接口中定义execute方法,类似JDK提供的TimeTask类的run方法,在里面编写任务执行的业务逻辑
  • Job实例在Quartz中的生命周期:每次调度器执行job时,它在调用execute方法前会创建一个新的job实例,当调用完成后,关联的Job对象实例会被释放,释放的实例会被垃圾回收机制回收。
  • JobDetail:JobDetail为Job实例提供了许多设置属性,以及JobDataMap成员变量属性,它用来存贮特定Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例。
  • JobDetail重要属性:name、group、jobClass、jobDataMap
//创建JobDetail(作业信息)
        JobDetail jb = JobBuilder.newJob(MyJob.class)
                .withDescription("this is a test job") //job的描述
                .withIdentity("testJob", "testGroup") //job 的name和group
                .build();
7.2 JobExecutionContext介绍
  • 当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法
  • Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据
7.3 JobDataMap介绍
  • 在进行任务调度时,JobDataMap存储在JobExecutionContext中,非常方便获取
  • JobDataMap可以用来装在任何可序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它
  • JobDataMap实现了JDK的Map接口,并且添加了非常方便的方法用来存取基本数据类型
 //3.创建JobDetail(作业信息)
        JobDetail jb = JobBuilder.newJob(MyJob.class)
                .withDescription("this is a test job") //job的描述
                .withIdentity("testJob", "testGroup") //job 的name和group
                .build();
                   //4.创建Trigger
        //使用SimpleScheduleBuilder或者CronScheduleBuilder
        Trigger t = TriggerBuilder.newTrigger()
                .withDescription("")
                .withIdentity("ramTrigger", "ramTriggerGroup")
                .startAt(statTime)  //默认当前时间启动
                //普通计时器
                //.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).withRepeatCount(3))//间隔3秒,重复3次
                //表达式计时器
                .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?")) //3秒执行一次
                .build();
  • Job实现类中添加setter方法对应jobDataMap的键值,Quartz框架默认的jobFactory实现类在初始化job实例对象时会自动的调用这些setter方法
 private String message;
    public void setMessage(String message) {
        this.message = message;
    }
  1. 这里注意:如果遇到同名的key,Trigger中的.usingJobData(“message”,“simple触发器”)会覆盖JobDetail中的.usingJobData(“message”,“打印日志”)。
7.4 有状态的Job和无状态的Job

@PersistJobDataAfterExecution注解的使用

  1. 有状态的Job可以理解为多次Job调用期间可以持有一些状态信息,这些状态信息存储在JobDataMap中,而默认的无状态Job每次调用时都会创建一个新的jobDataMap.
  2. 具体代码实现可以初始化一个count变量设为自增来计数,使用注解和不使用注解分别打印一下count的值,看是否是新建的job

8. Trigger详解

在这里插入图片描述Quartz有一些不同的触发器类型,不过,用得最多的是SimpleTrigger和CronTrigger

  1. jobKey
    表示job实例的标识,触发器被触发时,该指定的job实例会被执行,
  2. startTime
    表示触发器的时间表,第一次开始被触发的时间,它的数据类型是java.util.Data
  3. endTime
    指定触发器终止被触发的时间,它的数据类型是java.util.Data.
    案例:
public class DemoQuartz {
    public static void main(String[] args) throws Exception {
        //1.创建Scheduler的工厂
        SchedulerFactory sf = new StdSchedulerFactory();

        //2.从工厂中获取调度器实例
        Scheduler scheduler = sf.getScheduler();

        Date stdate = new Date();
        stdate.setTime(stdate.getTime());
        Date enddate = new Date();
        enddate.setTime(enddate.getTime()+10000);

        //3.创建JobDetail(作业信息)
        JobDetail jb = JobBuilder.newJob(MyJob.class)
                .withDescription("this is a test job") //job的描述
                .withIdentity("testJob", "testGroup") //job 的name和group
                .usingJobData("message","打印日志")
                .build();


        //向任务传递数据
        JobDataMap jobDataMap = jb.getJobDataMap();
        jobDataMap.put("JobDataMap传参", "测试");

        /*//任务运行的时间,SimpleSchedle类型触发器有效
        long time = System.currentTimeMillis() + 3 * 1000L; //3秒后启动任务
        Date statTime = new Date(time);*/

        //4.创建Trigger
        //使用SimpleScheduleBuilder或者CronScheduleBuilder
        Trigger t = TriggerBuilder.newTrigger()
                .withDescription("")
                .withIdentity("ramTrigger", "ramTriggerGroup")
                .startAt(stdate)  //默认当前时间启动
                .endAt(enddate)//结束时间
                //普通计时器
                //.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).withRepeatCount(3))//间隔3秒,重复3次
                //表达式计时器
                .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?")) //3秒执行一次
                .usingJobData("message","simple触发器")
                .build();

        //5.注册任务和定时器
        scheduler.scheduleJob(jb, t);

        //6.启动 调度器
        scheduler.start();

    }
}
public class MyJob implements Job {
    private String message;
    public void setMessage(String message) {
        this.message = message;
    }

    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("定时器任务执行,当前时间为:" + new Date(System.currentTimeMillis()));
        Date  date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = dateFormat.format(date);
        //System.out.println("执行定时任务,当前时间为:"+dateString);

        Trigger trigger = context.getTrigger();
        System.out.println("jobKey标识:"+trigger.getJobKey().getName()+
                "jobKey组名称"+trigger.getJobKey().getGroup());
        System.out.println("开始时间:"+dateFormat.format(trigger.getStartTime())+
                "结束时间:"+dateFormat.format(trigger.getEndTime()));

        JobDataMap map=context.getMergedJobDataMap();
        System.out.println("JobDataMap参数值:"+map.get("JobDataMap传参"));
    }
}

9. SimpleTrigger触发器

  • SimpleTrigger对于设置和使用是最为简单的一种QuartzTrigger。它是为那种需要在特定的日期/时间启动,且以一个可能的时间间隔时间重复执行n次的job所设计的。
    案例就省略掉了,你们自己可以尝试修改参数
  • 需要注意的点
    1. SimpleTrigger的属性有:开始时间、结束时间、重复次数和重复的时间间隔
    2. 重复次数属性的值可以为0,正整数,或常量SimpleTrigger.REPEAT_INDEFINITELY
    3. 重复的时间间隔属性值必须为0或长整型的正整数,以毫秒作为时间单位,当重复的时间间隔为0时,意味着与Trigger同时触发执行
    4. 如果有指定结束时间属性值,则结束时间属性优先于重复次数属性,这样的好处在于:当我们需要创建一个每间隔十秒钟触发一次直到指定的结束时间的Trigger,而无需去计算从开始到结束的所重复的次数,我们只需简单的指定结束时间和使用REPEAT_INDEFINITELY作为重复次数的属性值即可。

10. CrinTrigger触发器

  • 如果你需要像日历那样按照日程来触发任务,而不是像SimpleTrigger那样每隔特定的时间间隔触发,CrinTriggers通常比SimpleTrigger更有用,因为它是基于日历的作业调度器。使用CrinTrigger,你可以指定诸如"每个周五中午",或者“每个工作日的9:30”或"从每周一周三周五的上午9:00到上午10:00之间每隔五分钟"这样日程安排来触发,甚至像SimpleTrigger一样,CrinTrigger也有一个starttime以指定日程从什么时候开始,也有一个可选的endtime指定何时日程不在继续。
10.1 Crin Expressions–Cron表达式
  • Cron表达式被用来配置CrinTrigger实例,Cron表达式是一个由7个子表达式组成的字符串,每个子表达式都描述了一个单独的日程细节,这些子表达式用空格分隔,分别表示:
    1. Seconds 秒
    2. Minutes 分钟
    3. Hours 小时
    4. Day-of-Month 月中的天
    5. Month 月
    6. Day-of-Week 周中的天
    7. Year 年(可选的域)
      取值为:
      在这里插入图片描述
  • 所有的域中的值都有特定的合法范围,这些值的合法范围相当明显,就不用了举例了
  • 符号解释如下:
    在这里插入图片描述
    举例如下:

在这里插入图片描述

  • 可以在网页中的在线转换工具在线转换你想要的定时任务表达式
    未完待续…
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值