当前位置: 首页 > news >正文

Quartz认知篇 - 初识分布式任务调度Quartz

定时任务的使用场景

在遇到如下几种场景可以考虑使用定时任务来解决:

  • 某个时刻或者时间间隔执行任务
  • 批量数据进行处理
  • 对两个动作进行解耦

Quartz

介绍

Quartz 是一个特性丰富的、开源的任务调度库,几乎可以嵌入所有的 Java 程序,包括很小的独立应用程序到大型商业系统。Quartz 可以用来创建成百上千的简单的或者复杂的任务,并且这些任务可以作为执行任何事情的标准 Java 组件。Quartz 拥有很多企业级别的特性,包括支持 JTA 事务和集群。

Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.

体系结构

在这里插入图片描述

配置触发的规则

定义要执行的任务,代码/脚本

集中管理配置

并发执行任务,互不干扰

调度器控制任务的生命周期

可以集成 Spring、Spring Boot

任务

可以实现 Job 接口来定义一个任务,然后重写它的 execute 方法来定义任务执行的逻辑。

public class MyJob implements Job {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyJob.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        LOGGER.info(simpleDateFormat.format(new Date()) + ", 任务1执行了, " + jobDataMap.getString("hello"));
    }
}

而调度器的调度方法需要指定一个 JobDetail,即任务明细。JobDetail 可以通过 JobBuilder 的相关方法进行实例化。

JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
        .withIdentity("myJob", "my-job-group")
        .usingJobData("hello", "tom")
        .usingJobData("hi", "selina")
        .build();

接下来,看下 JobBuilder 中定义的一些比较重要的方法。

1、newJob 方法

实例化 JobBuilder(可以指定一个任务)

public static JobBuilder newJob() {
  return new JobBuilder();
}

public static JobBuilder newJob(Class<? extends Job> jobClass) {
  JobBuilder b = new JobBuilder();
  b.ofType(jobClass);
  return b;
}

2、ofType 方法

指定任务

public JobBuilder ofType(Class<? extends Job> jobClazz) {
  this.jobClass = jobClazz;
  return this;
}

3、withIdentity 方法

指定任务的名字和组

public JobBuilder withIdentity(String name) {
  key = new JobKey(name, null);
  return this;
}

public JobBuilder withIdentity(String name, String group) {
  key = new JobKey(name, group);
  return this;
}

public JobBuilder withIdentity(JobKey jobKey) {
  this.key = jobKey;
  return this;
}

4、withDescription 方法

指定任务的描述

public JobBuilder withDescription(String description) {
  this.description = description;
  return this;
}

5、requestRecovery 方法

指定任务遇到“recovery”或者“fail-over”情形是否应该重新执行

public JobBuilder requestRecovery() {
  this.shouldRecover = true;
  return this;
}

public JobBuilder requestRecovery(boolean jobShouldRecover) {
  this.shouldRecover = jobShouldRecover;
  return this;
}

6、storeDurably 方法

指定任务是否应该持久化

public JobBuilder storeDurably() {
  this.durability = true;
  return this;
}

public JobBuilder storeDurably(boolean jobDurability) {
  this.durability = jobDurability;
  return this;
} 

7、usingJobData 方法

添加一组键值对到 JobDetail 的 JobDataMap 属性中

public JobBuilder usingJobData(String dataKey, String value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Integer value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Long value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Float value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Double value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(String dataKey, Boolean value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public JobBuilder usingJobData(JobDataMap newJobDataMap) {
  jobDataMap.putAll(newJobDataMap);
  return this;
}

8、setJobData 方法

覆盖 JobDetail 的 JobDataMap 属性

public JobBuilder setJobData(JobDataMap newJobDataMap) {
  jobDataMap = newJobDataMap;
  return this;
}

9、build 方法

构建 JobDetailImpl 实例

public JobDetail build() {

    JobDetailImpl job = new JobDetailImpl();
    
    job.setJobClass(jobClass);
    job.setDescription(description);
    if(key == null)
        key = new JobKey(Key.createUniqueName(null), null);
    job.setKey(key); 
    job.setDurability(durability);
    job.setRequestsRecovery(shouldRecover);
    
    
    if(!jobDataMap.isEmpty())
        job.setJobDataMap(jobDataMap);
    
    return job;
}

触发器

任务触发的规则。

调度器的调度方法需要指定一个 Trigger 实例,即触发器。可以通过 TriggerBuilder 的相关方法构建一个 Trigger 实例。

Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("myTrigger", "my-trigger-group")
        .startNow()
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(5)
                .repeatForever())
        .build();

接下来看下 TriggerBuilder 定义的一些比较重要的方法。

1、newTrigger 方法

构建 TriggerBuilder 实例

public static TriggerBuilder<Trigger> newTrigger() {
  return new TriggerBuilder<Trigger>();
}

2、withIdentity 方法

设置触发器的名字和组名

public TriggerBuilder<T> withIdentity(String name) {
  key = new TriggerKey(name, null);
  return this;
}

public TriggerBuilder<T> withIdentity(String name, String group) {
  key = new TriggerKey(name, group);
  return this;
}

public TriggerBuilder<T> withIdentity(TriggerKey triggerKey) {
  this.key = triggerKey;
  return this;
}

3、withDescription 方法

设置触发器的描述

public TriggerBuilder<T> withDescription(String triggerDescription) {
  this.description = triggerDescription;
  return this;
}

4、withPriority 方法

设置触发器的优先级(如果有多个启动时间相同的触发器,根据触发器的优先级由大到小的顺序进行启动)

public TriggerBuilder<T> withPriority(int triggerPriority) {
  this.priority = triggerPriority;
  return this;
}

5、modifiedByCalendar 方法

设置应用到该触发器调度的 Calendar 的名字

public TriggerBuilder<T> modifiedByCalendar(String calName) {
  this.calendarName = calName;
  return this;
}

6、startAt 方法

设置触发器的开始时间

public TriggerBuilder<T> startAt(Date triggerStartTime) {
  this.startTime = triggerStartTime;
  return this;
}

7、startNow 方法

设置触发器立即开始

public TriggerBuilder<T> startNow() {
  this.startTime = new Date();
  return this;
}

8、endAt 方法

设置触发器的结束时间

public TriggerBuilder<T> endAt(Date triggerEndTime) {
  this.endTime = triggerEndTime;
  return this;
}

9、withSchedule 方法

设置用于触发器调度的 ScheduleBuilder

public <SBT extends T> TriggerBuilder<SBT> withSchedule(ScheduleBuilder<SBT> scheduleBuilder) {
  this.scheduleBuilder = scheduleBuilder;
  returnt (TriggerBuilder<SBT>) this;
}

10、forJob 方法

设置触发器关联的任务

public TriggerBuilder<T> forJob(JobKey jobKey) {
  this.jobKey = jobKey;
  return this;
}

public TriggerBuilder<T> forJob(String jobName) {
  this.jobKey = new JobKey(jobName, null);
  retun this;
}

public TriggerBuilder<T> forJob(String jobName, String jobGroup) {
  this.jobKey = new JobKey(jobName, jobGroup);
  return this;
}

public TriggerBuilder<T> forJob(JobDetail jobDetail) {
  JobKey k = jobDetail.getKey();
  if (k.getName() == null) {
    throw new IllegalArgumentException("The given job has not yet had a name assigned to it.");
  }
  this.jobKey = k;
  return this;
}

11、usingJobData 方法

添加一组键值对到触发器的 JobDataMap 属性中

public TriggerBuilder<T> usingJobData(String dataKey, String value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, String value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Integer value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Long value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Float value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Double value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(String dataKey, Boolean value) {
  jobDataMap.put(dataKey, value);
  return this;
}

public TriggerBuilder<T> usingJobData(JobDataMap newJobDataMap) {
  for(String dataKey: jobDataMap.keySet()) {
    newJobDataMap.put(dataKey, jobDataMap.get(dataKey));
  }
  jobDataMap = newJobDataMap; 
  return this;
}

12、build 方法

构建具体的 Trigger 实例

public T build() {

    if(scheduleBuilder == null)
        scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
    MutableTrigger trig = scheduleBuilder.build();
    
    trig.setCalendarName(calendarName);
    trig.setDescription(description);
    trig.setStartTime(startTime);
    trig.setEndTime(endTime);
    if(key == null)
        key = new TriggerKey(Key.createUniqueName(null), null);
    trig.setKey(key); 
    if(jobKey != null)
        trig.setJobKey(jobKey);
    trig.setPriority(priority);
    
    if(!jobDataMap.isEmpty())
        trig.setJobDataMap(jobDataMap);
    
    return (T) trig;
}

SimpleTrigger

时间间隔执行n次(时分秒)

1、simpleSchedule 方法

构建 SimpleScheduleBuilder 实例

public static SimpleScheduleBuilder simpleSchedule() {
    return new SimpleScheduleBuilder();
}

2、repeat…Forever 方法

指定时间间隔,永久重复执行

// 指定每隔一分钟永久重复执行
public static SimpleScheduleBuilder repeatMinutelyForever() {
    return simpleSchedule()
        .withIntervalInMinutes(1)
        .repeatForever();
}

// 指定每隔多少分钟永久重复执行
public static SimpleScheduleBuilder repeatMinutelyForever(int minutes) {
    return simpleSchedule()
        .withIntervalInMinutes(minutes)
        .repeatForever();
}

// 指定每隔一秒永久重复执行
public static SimpleScheduleBuilder repeatSecondlyForever() {
    return simpleSchedule()
        .withIntervalInSeconds(1)
        .repeatForever();
}

// 指定每隔多少秒永久重复执行
public static SimpleScheduleBuilder repeatSecondlyForever(int seconds) {
    return simpleSchedule()
        .withIntervalInSeconds(seconds)
        .repeatForever();
}

// 指定每隔一小时永久重复执行
public static SimpleScheduleBuilder repeatHourlyForever() {
    return simpleSchedule()
        .withIntervalInHours(1)
        .repeatForever();
}

// 指定每隔多少小时永久重复执行
public static SimpleScheduleBuilder repeatHourlyForever(int hours) {
    return simpleSchedule()
        .withIntervalInHours(hours)
        .repeatForever();
}

3、repeat…ForTotalCount 方法

指定时间间隔,重复执行直到指定次数

// 每隔一分钟重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatMinutelyForTotalCount(int count) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInMinutes(1)
        .withRepeatCount(count - 1);
}

// 每隔多少分钟重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatMinutelyForTotalCount(int count, int minutes) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInMinutes(minutes)
        .withRepeatCount(count - 1);
}

// 每隔一秒重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatSecondlyForTotalCount(int count) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInSeconds(1)
        .withRepeatCount(count - 1);
}

// 每隔多少秒重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatSecondlyForTotalCount(int count, int seconds) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInSeconds(seconds)
        .withRepeatCount(count - 1);
}

// 每隔一小时重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatHourlyForTotalCount(int count) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInHours(1)
        .withRepeatCount(count - 1);
}

// 每隔多少小时重复执行一次,直到指定次数
public static SimpleScheduleBuilder repeatHourlyForTotalCount(int count, int hours) {
    if(count < 1)
        throw new IllegalArgumentException("Total count of firings must be at least one! Given count: " + count);
    return simpleSchedule()
        .withIntervalInHours(hours)
        .withRepeatCount(count - 1);
}

4、withInterval… 方法

指定时间间隔,执行一次

// 每隔多少毫秒执行一次
public SimpleScheduleBuilder withIntervalInMilliseconds(long intervalInMillis) {
    this.interval = intervalInMillis;
    return this;
}

// 每隔多少秒执行一次
public SimpleScheduleBuilder withIntervalInSeconds(int intervalInSeconds) {
    this.interval = intervalInSeconds * 1000L;
    return this;
}

// 每隔多少分钟执行一次
public SimpleScheduleBuilder withIntervalInMinutes(int intervalInMinutes) {
    this.interval = intervalInMinutes * DateBuilder.MILLISECONDS_IN_MINUTE;
    return this;
}

// 每隔多少小时执行一次
public SimpleScheduleBuilder withIntervalInHours(int intervalInHours) {
    this.interval = intervalInHours * DateBuilder.MILLISECONDS_IN_HOUR;
    return this;
}

5、withRepeatCount 方法

指定重复执行的次数

public SimpleScheduleBuilder withRepeatCount(int triggerRepeatCount) {
    this.repeatCount = triggerRepeatCount;
    return this;
}

6、repeatForever 方法

指定永久重复执行

public SimpleScheduleBuilder repeatForever() {
    this.repeatCount = SimpleTrigger.REPEAT_INDEFINITELY;
    return this;
}

7、withMisfire 方法

设置触发器错过启动时间的补偿策略

public SimpleScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() {
    misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionFireNow() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionNextWithExistingCount() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionNextWithRemainingCount() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionNowWithExistingCount() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT;
    return this;
}

public SimpleScheduleBuilder withMisfireHandlingInstructionNowWithRemainingCount() {
    misfireInstruction = SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT;
    return this;
}

CalendarIntervalTrigger

时间间隔执行一次(年月周日时分秒)

1、calendarIntervalSchedule 方法

构建 CalendarIntervalScheduleBuilder 实例

public static CalendarIntervalScheduleBuilder calendarIntervalSchedule() {
  return new CalendarIntervalScheduleBuilder();
}

2、withInterval…方法

每隔多少时间间隔执行一次

// 每隔多少时间单位执行一次
public CalendarIntervalScheduleBuilder withInterval(int timeInterval, IntervalUnit unit) {
    if(unit == null)
        throw new IllegalArgumentException("TimeUnit must be specified.");
    validateInterval(timeInterval);
    this.interval = timeInterval;
    this.intervalUnit = unit;
    return this;
}

// 每隔多少秒执行一次
public CalendarIntervalScheduleBuilder withIntervalInSeconds(int intervalInSeconds) {
    validateInterval(intervalInSeconds);
    this.interval = intervalInSeconds;
    this.intervalUnit = IntervalUnit.SECOND;
    return this;
}

// 每隔多少分钟执行一次
public CalendarIntervalScheduleBuilder withIntervalInMinutes(int intervalInMinutes) {
    validateInterval(intervalInMinutes);
    this.interval = intervalInMinutes;
    this.intervalUnit = IntervalUnit.MINUTE;
    return this;
}

// 每隔多少小时执行一次
public CalendarIntervalScheduleBuilder withIntervalInHours(int intervalInHours) {
    validateInterval(intervalInHours);
    this.interval = intervalInHours;
    this.intervalUnit = IntervalUnit.HOUR;
    return this;
}

// 每隔多少天执行一次
public CalendarIntervalScheduleBuilder withIntervalInDays(int intervalInDays) {
    validateInterval(intervalInDays);
    this.interval = intervalInDays;
    this.intervalUnit = IntervalUnit.DAY;
    return this;
}

// 每隔多少周执行一次
public CalendarIntervalScheduleBuilder withIntervalInWeeks(int intervalInWeeks) {
    validateInterval(intervalInWeeks);
    this.interval = intervalInWeeks;
    this.intervalUnit = IntervalUnit.WEEK;
    return this;
}

// 每隔多少月执行一次
public CalendarIntervalScheduleBuilder withIntervalInMonths(int intervalInMonths) {
    validateInterval(intervalInMonths);
    this.interval = intervalInMonths;
    this.intervalUnit = IntervalUnit.MONTH;
    return this;
}

// 每隔多少年执行一次
public CalendarIntervalScheduleBuilder withIntervalInYears(int intervalInYears) {
    validateInterval(intervalInYears);
    this.interval = intervalInYears;
    this.intervalUnit = IntervalUnit.YEAR;
    return this;
}

3、withMisfire… 方法

设置触发器错过启动时间的补偿策略

public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionIgnoreMisfires() {
    misfireInstruction = Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY;
    return this;
}

public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionDoNothing() {
    misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_DO_NOTHING;
    return this;
}

public CalendarIntervalScheduleBuilder withMisfireHandlingInstructionFireAndProceed() {
    misfireInstruction = CalendarIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;
    return this;
}

4、inTimeZone 方法

设置时区

public CalendarIntervalScheduleBuilder inTimeZone(TimeZone timezone) {
    this.timeZone = timezone;
    return this;
}

5、build 方法

构建 CalendarIntervalTriggerImpl 实例

@Override
public MutableTrigger build() {
    CalendarIntervalTriggerImpl st = new CalendarIntervalTriggerImpl();
    st.setRepeatInterval(interval);
    st.setRepeatIntervalUnit(intervalUnit);
    st.setMisfireInstruction(misfireInstruction);
    st.setTimeZone(timeZone);
    st.setPreserveHourOfDayAcrossDaylightSavings(preserveHourOfDayAcrossDaylightSavings);
    st.setSkipDayIfHourDoesNotExist(skipDayIfHourDoesNotExist);
    return st;
}

DailyTimeIntervalTrigger

CronTrigger

相关文章:

  • 网站访客qq获取/如何投放网络广告
  • 印尼做网站的教学 中文/西安seo外包优化
  • 咸宁网站制作培训/数据分析师要学什么
  • 合肥的网站建设公司哪家好/网络营销的发展趋势
  • 家装设计需要学什么软件/seo刷关键词排名工具
  • 网站建设流程和费用/网络服务器价格
  • 论文解读 - 城市自动驾驶车辆运动规划与控制技术综述 (第2部分)
  • Puppeteer之Pyppeteer——定位页面元素的正确方法(3)
  • 简述团队模式和团队的开发模式
  • 动态内存分配/管理
  • subprocess模块
  • silicon labs Gateway HOST-NCP MQTT网关搭建
  • 《深入浅出计算机组成原理》学习笔记 Day1
  • 蚂蚁智能内容合规产品,提供一站式营销合规管控解决方案
  • 怎么恢复360删除的文件?360文件恢复,快速完成
  • SpringCloud-Netflix学习笔记06——Eureka对比Zookeeper
  • 【数据结构和算法】栈—模拟实现Stack和栈相关算法题
  • 迪文屏OS汇编代码开发-参数修改 保存 翻页(七)