定时任务框架Quartz使用教程

概述

Quartz 是一个功能丰富开放源码的任务调度框架。几乎可以集成到任何Java应用程序中——从最小的独立应用程序到最大的电子商务系统。可以创建简单或者复杂的调度用来执数十个甚至成百上万个作业;Quartz功能强大可以让你的程序在指定时间执行,也可以按照某一个频度执行,支持数据库、监听器、插件、集群等特性。
使用场景:定时消息推送、定时抢购、定时发送邮件、定时统计等。

环境搭建

一、 引入Maven相关pom依赖

    <!--quartz相关依赖-->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.0</version>
    </dependency>

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

二、定义需要执行的任务内容,例如:输入当前系统时间

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;


/**
 * 定义要执行的任务内容
 */
public class MyQuartzJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //输出系统当前时间
        System.err.println("系统当前时间为+"+new Date());
    }
}

三、构建调度任务

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;



public class QuartzTest{
    public static void main(String[] args) {

        try {

            //获取调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            //包装任务内容JobDetail
            JobDetail jobDetail = JobBuilder.newJob(MyQuartzJob.class)
                    //定义name和group
                    .withIdentity("job1", "group1")
                    .usingJobData("name","今天天气不错")
                    .build();

            //定义Trigger触发器
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger", "group1")
                    //立即执行
                    .startNow()
                    //定时,每隔一秒钟执行一次
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(1)
                            //重复执行
                            .repeatForever())
                    .build();

            //组装任务
            scheduler.scheduleJob(jobDetail,trigger);
            //启动调度器  开始调度
            scheduler.start();
            //运行一段时间后(10秒)关闭任务
            Thread.sleep(10000);
            scheduler.shutdown();
        } catch (SchedulerException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果如下图:
在这里插入图片描述

三、体系架构

Quartz的三要素:
Scheduler、Trigger、JobDetail & Job

Job:

是一个接口,接口中只定义了一个execute方法
void execute(JobExecutionContext var1) throws JobExecutionException;
通过实现接口中的execute方法,在方法中编写所需要定时执行的Job(任务),JobExecutionContext类提供了调度应用的一些信息。
Job运行时的信息保存在JobDataMap实例中。

JobDetail:

JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。
scheduler每次执行, 都会根据JobDetail创建一个新的job实例。
为什么需要有个JobDetai来作为job的定义,为什么不直接使用job?
解释:如果使用jobdetail来定义,那么每次调度都会创建一个new job实例,这样带来的好处就是任务并发执行的时候,互不干扰,不会对临界资源造成影响。

Scheduler

org.quartz.Scheduler非常重要是Quartz 调度程序的主要接口,用于组装jobDetail和trigger开始任务调度。
Scheduler维护了一个JobDetails 和Triggers的注册表。一旦在Scheduler注册过了,当定时任务触发时间一到,调度程序就会负责执行预先定义的Job。
调度程序Scheduler实例是通过SchedulerFactory工厂来创建的。
SchedulerFactory调度程序工厂,有两个默认的实现类:
DirectSchedulerFactory和StdSchedulerFactory。

DirectSchedulerFactory:
DirectSchedulerFactory是一个org.quartz.SchedulerFactory的单例实现。

StdSchedulerFactory:
是基于Quartz属性文件创建Quartz Scheduler 调度程序的,一般我们用这个偏多。
默认情况下是加载当前工作目录下的”quartz.properties”属性文件。如果加载失败,会去加载org/quartz包下的”quartz.properties”属性文件。

JobBulider

用于定义/构建已经定义了Job实例的JobDetail实例

TriggerBuilder

用于定义/构建Trigger实例。

Trigger:

是一个类,描述触发]ob执行的时间触发规则。主要有SimpleTrigger和CronTrigger这两个子类。
当且仅当需调度一次或者以固定时间间隔周期执行调度, SimpleTrigger是最适合的选择;
而CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度方案:如工作日周一到周
五的15: 00~16: 00执行调度等
Trigger常用方法:
withIdentity:定义触发器一些属性 比如名字,组名。
usingJobData():给具体job传递参数
startNow():触发器立即执行
withSchedule():以哪种触发器出发
startAt() : 开始时间(java.util.Date)
endAt() : 结束时间,设置了结束时间则在这之后,不再触发
Trigger的重点内容就是在**withSchedule()**这个方法,一共有四种具体实现方法,分别是:
1、SimpleScheduleBuilder
2、DailyTimeIntervalScheduleBuilder
3、CalendarIntervalScheduleBuilder
4、CronScheduleBuilder
下面分别介绍一下:
一、SimpleScheduleBuilder:
最简单的触发器,表示从某一时刻开始,以一定的时间间隔执行任务。
属性:
repeatInterval 重复间隔。
repeatCount 重复次数。
例如:从现在开始,每分钟执行一次。

 //定义Trigger触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "group1")
                //立即执行
                .startNow()
                //定时,每隔一秒钟执行一次
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(1)
                        //重复执行
                        .repeatForever())
                .build();

二、DailyTimeIntervalScheduleBuilder:
每一天的某一个时间段内,以一定的时间间隔执行任务,可以指定具体的某一天(星期一、星期二~~)
属性:
withIntervalInHours 重复间隔(秒、分钟、小时。。。)。
onDaysOfTheWeek 具体的星期。 默认 周一到周日
startingDailyAt 每天开始时间 默认 0.0
endingDailyAt 每天结束时间,默认 23.59.59
repeatCount 重复次数。 默认是-1 不限次数
interval 每次执行间隔

例如:比如每周一到周五中午12点开始,下午16点结束,每次执行间隔1 小时。

            //定义Trigger触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "group1")
                //立即执行
                .startNow()
       .withSchedule(dailyTimeIntervalSchedule()
                        .startingDailyAt(TimeOfDay.hourAndMinuteOfDay(12, 00)) //每天12:00开始
                        .endingDailyAt(TimeOfDay.hourAndMinuteOfDay(16, 0)) //16:00 结束
                        .onDaysOfTheWeek(SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY) //周一至周五执行
                        .withIntervalInHours(1)) //每间隔1小时执行一次
                .build();

三、CalendarIntervalScheduleBuilder:
和SimpleScheduleBuilder类似,都是表示从某一时刻开始,以一定时间间隔执行任务。
但是SimpleScheduleBuilder无法指定一些特殊情况,比如每月执行一次,每周执行一次、每年执行一次
属性:
interval 执行间隔
intervalUnit 执行间隔的单位(秒,分,小,天,月,年,周)
例如:

        //定义Trigger触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "group1")
                //立即执行
                .startNow()
               .withSchedule(calendarIntervalSchedule()
                        .withIntervalInWeeks(1) //每周执行一次
                ).build();

四、CronScheduleBuilder:
通过cron表达式可以定义任意规则,实现以上的任意需求。

    //定义Trigger触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "group1")
                //立即执行
                .startNow()
                .withSchedule(cronSchedule("0 0/1 8-17 * * ?") // 每天8:00-17:00,每隔2分钟执行一次
                ).build();

cron表达式的格式:秒、分、时、日、月、周、年(可选)
在这里插入图片描述
允许的特殊字符:

  1. “?”字符:表示不确定的值
  2. ","字符:指定数个值
  3. "-"字符:指定一个值的范围
  4. "/"字符:指定一个值的增加幅度。n/m表示从n开始,每次增加m
  5. "L"字符:用在日表示一个月中的最后一天,用在周表示该月最后一个星期X
  6. "W"字符:指定离给定日期最近的工作日(周一到周五)
  7. "#"字符:表示该月第几个周X。6#3表示该月第3个周五

可通过在线生成Cron表达式的工具:http://cron.qqe2.com/ 来生成自己想要的表达式。

总结:

如果项目中出现定时任务并发执行的情况可以在job类上加上注解@DisallowConcurrentExecution来解决。
注意:@DisallowConcurrentExecution是对JobDetail实例生效,如果一个job类被不同的jobdetail引用,这样是可以并发执行。
如果是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>

Quartz定时任务框架开源且非常强大,用起来非常方便,几乎可以应用到任何java程序中,网上教程很多,但是归结起来大同小异,本文代码非常详细,之后介绍Quartz集成到Spring框架中以及Quartz集群的使用教程。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Quartz是一种广泛使用的分布式定时作业调度框架,可用于在多台服务器上触发执行一组作业。以下是Quartz分布式定时任务框架的搭建步骤: 1. 安装数据库 Quartz框架需要一个持久性存储器来保存作业调度信息。选择一个数据库(如MySQL或Oracle)并创建Quartz的表结构。 2. 配置Quartz实例 在Quartz中,每个实例代表一个独立的调度器,可以在其上启动和停止作业调度。要配置Quartz实例,需要在代码中指定一些配置属性,例如数据库连接信息和调度器的名称。 3. 创建作业和触发器 在Quartz中,作业代表要执行的代码逻辑,而触发器则指定作业何时运行。可以使用Cron表达式来指定触发器的运行时间。要创建新的作业和触发器,请使用Quartz的API。 4. 创建分布式Quartz实例 为了使Quartz在分布式环境中运行,需要在所有服务器上创建Quartz实例。这些实例应该使用相同的数据库,并且应该使用相同的配置属性。 5. 配置集群 在分布式环境中,Quartz需要一种机制来协调调度器的运行。可以通过使用第三方插件(如Terracotta)或Quartz提供的基于数据库的集群实现来实现这一点。 6. 启动Quartz实例 一旦完成了配置和集群设置,可以启动Quartz实例并开始调度作业。要启动Quartz实例,需要使用Quartz的API方法。 总之,搭建Quartz分布式定时任务框架需要一定的技术和经验。最好在熟悉Quartz框架之前不要尝试这个任务。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值