千家信息网

Quartz 中Trigger的作用是什么

发表于:2025-02-05 作者:千家信息网编辑
千家信息网最后更新 2025年02月05日,本篇文章给大家分享的是有关Quartz 中Trigger的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Trigger的公共属
千家信息网最后更新 2025年02月05日Quartz 中Trigger的作用是什么

本篇文章给大家分享的是有关Quartz 中Trigger的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

Trigger的公共属性

triggerKey:表示Trigger身份的属性

jobKey:Trigger触发时被执行的Job的身份

startTime:Trigger第一次触发的时间

endTime:Trigger失效的时间点

Trigger的其它属性

优先级(priority):如果Trigger很多,或者Quartz线程池的工作线程太少,Quartz可能没有足够的资源同事触发所有的Trigger,这种情况下,如果希望某些Trigger优先被触发,就需要给它设置优先级,Trigger默认的优先级为5,优先级priority属性的值可以是任意整数,正数、负数都可以。(只有同时触发的Trigger之间才会比较优先级)

错失触发(misfire):如果Scheduler关闭了,或者Quartz线程池中没有可用的线程来执行Job,此时持久性的Trigger就会错过其触发时间,即错失触发。不同类型的Trigger,有不同的misfire机制,它们都默认使用"智能机制(smart policy)",即根据Trigger的类型和配置动态调整行为,当Scheduler启动的时候,查询所有错过触发机制的持久性Trigger,然后根据它们各自的misfire机制更新Trigger的信息。

日历(Calendar)示例

Quartz的Calendar对象(不是java.util.Calendar对象)可以在定义和存储trigger的时候与trigger进行关联。Calendar用于从trigger的调度计划中排除时间段。

各种常用Trigger

SimpleTrigger

指定从某一个时间开始,以一定时间间隔(单位:毫秒)执行的任务。

它的属性有:

repeatInterval:重复间隔

repeatCount:重复次数,实际执行次数是repeatCount+1(因为在startTime的时候一定会执行一次)

SimpleTrigger trigger = newTrigger()       .withIdentity("trigger1", "group1")       .startAt(futureDate(5, DateBuilder.IntervalUnit.SECOND))       .withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10))       .endAt(dateOf(18, 0, 0))       .forJob(job)       .build();

注意:endTime属性的值会覆盖repeatCount的属性值。

TriggerBuilder(以及Quartz的其他Builder)会为那些没有被显示设置的属性选择合理的默认值,例如:如果没有调用withIdentity(..)方法,TriggerBuilder会为trigger生成一个随机的名称;如果没有调用startAt(..)方法,则默认使用当前时间,即trigger立即生效。

CalendarIntervalTrigger

类似于SimpleTrigger,指定从某一个时间开始,以一定的时间间隔执行的任务。 但是不同的是SimpleTrigger指定的时间间隔为毫秒,没办法指定每隔一个月执行一次(每月的时间间隔不是固定值),而CalendarIntervalTrigger支持的间隔单位有秒,分钟,小时,天,月,年,星期。

相较于SimpleTrigger有两个优势:

1、更方便,比如每隔1小时执行,你不用自己去计算1小时等于多少毫秒

2、支持不是固定长度的间隔,比如间隔为月和年。但劣势是精度只能到秒

它的属性有:

interval 执行间隔

intervalUnit 执行间隔的单位(秒,分钟,小时,天,月,年,星期)

CalendarIntervalTrigger trigger = newTrigger()       .withIdentity("trigger1", "group1")       .startNow()       .withSchedule(calendarIntervalSchedule().withInterval(10, DateBuilder.IntervalUnit.SECOND))       //.withSchedule(calendarIntervalSchedule().withIntervalInDays(1))       .endAt(dateOf(18, 0, 0))       .forJob(job)       .build();

DailyTimeIntervalTrigger

指定每天的某个时间段内,以一定的时间间隔执行任务。并且它可以支持指定星期。

它的属性有:

startTimeOfDay 每天开始时间

endTimeOfDay 每天结束时间

daysOfWeek 需要执行的星期

interval 执行间隔

intervalUnit 执行间隔的单位(秒,分钟,小时,天,月,年,星期)

repeatCount 重复次数

DailyTimeIntervalTrigger trigger = newTrigger()       .withIdentity("trigger1", "group1")       .startNow()       .withSchedule(dailyTimeIntervalSchedule()               .onDaysOfTheWeek(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY) //周一至周五执行               .withInterval(10, DateBuilder.IntervalUnit.SECOND))       .forJob(job)       .build();

CronTrigger

适合于更复杂的任务,它支持类型于Linux Cron的语法(并且更强大)。

CronTrigger trigger = newTrigger()       .withIdentity("trigger1", "group1")       .startNow()       .withSchedule(cronSchedule("*/1 * * * * ?"))       .forJob(job)       .build();

注意:如果一些调度要求太复杂,无法用单一触发表示,那么就应该创建多个Trigger,Job和Trigger是松耦合的,一个Job可以定义多个Trigger。

public class HelloJob implements Job {   @Override   public void execute(JobExecutionContext context) throws JobExecutionException {       try {           JobDetail job = context.getJobDetail();           String name = job.getJobDataMap().getString("name");           Trigger trigger = context.getTrigger();           System.out.println("Run By Trigger: " + trigger.getKey() + ", hello " + name + " at " + new Date());       } catch (Exception e) {           e.printStackTrace();       }   }}
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();scheduler.start();JobDetail job = newJob(HelloJob.class)       .withIdentity("job1", "group1")       .usingJobData("name", "quartz").build();CronTrigger trigger1 = newTrigger()       .withIdentity("trigger1", "group1")       .startNow()       .withSchedule(cronSchedule("*/5 * 9-12 * * ?"))       .forJob(job)       .build();CronTrigger trigger2 = newTrigger()       .withIdentity("trigger2", "group1")       .startNow()       .withSchedule(cronSchedule("0 */1 14-18 * * ?"))       .forJob(job)       .build();Set triggerSet = new HashSet<>();triggerSet.add(trigger1);triggerSet.add(trigger2);scheduler.scheduleJob(job, triggerSet, true);try {   Thread.sleep(1000L * 60L * 10L);} catch (InterruptedException e) {   e.printStackTrace();}scheduler.shutdown();

Misfire策略

MISFIRE_INSTRUCTION_SMART_POLICY:所有Trigger的MisFire默认策略,即:把处理逻辑交给从Smart的Quartz去决定。

基本策略:

> 如果是只执行一次的调度,使用MISFIRE_INSTRUCTION_FIRE_NOW

> 如果是无限次的调度(repeatCount是无限的),使用MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT

> 否则,使用MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT

MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY:忽略MisFire策略,在资源适合的时候,重新出发所有MisFire任务,不影响现有的调度

SimpleTrigger Misfire策略

MISFIRE_INSTRUCTION_FIRE_NOW:忽略已经MisFire的任务,并且立即执行调度,通常只适用于只执行一次任务的场景

MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT:将startTime设置为当前时间,立即重新调度任务,包括MisFire的任务

MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT:与上一个策略类似,区别在于该策略会忽略MisFire的任务

MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT:在下一次调度的时间点,重新开始调度任务,包括MisFire的任务

MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT:与上一个策略类似,区别在于该策略会忽略MisFire的任务

CronTrigger Misfire策略

MISFIRE_INSTRUCTION_DO_NOTHING:什么都不做,继续等下一次调度时间再触发

MISFIRE_INSTRUCTION_FIRE_NOW:忽略已经MisFire的任务,并且立即执行调度,通常只适用于只执行一次任务的场景

Listeners

Listener用于在调度过程中监听事件操作,不过,大多数情况下,用户并不会使用Listener。JobListener、TriggerListener、SchedulerListener的用法类似,无非就是addXXXListener()、removeXXXListener()的操作,下面以JobListener为例介绍:

创建一个自定义的JobListener:

public class MyJobListener implements JobListener {   @Override   public String getName() {       System.out.println("getName()");       return "getName()";   }   @Override   public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {       System.out.println("jobToBeExecuted()");   }   @Override   public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {       System.out.println("jobExecutionVetoed()");   }   @Override   public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {       System.out.println("jobWasExecuted()");   }}

使用JobListener:

public class JobListenerDemo {   public static void main(String[] args) {       try {           Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();           MyJobListener myJobListener = new MyJobListener();           //添加监听           scheduler.getListenerManager().addJobListener(myJobListener, KeyMatcher.keyEquals(jobKey("job1", "group1")));           //scheduler.getListenerManager().addJobListener(new MyJobListener(), GroupMatcher.groupEquals("group1"));           //移除监听           //scheduler.getListenerManager().removeJobListener(myJobListener.getName());           scheduler.start();           JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1")                   .usingJobData("name", "quartz").build();           Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startNow()                   .withSchedule(simpleSchedule().withIntervalInSeconds(1).repeatForever()).build();           scheduler.scheduleJob(job, trigger);           try {               Thread.sleep(1000L * 60L * 10L);           } catch (InterruptedException e) {               e.printStackTrace();           }           scheduler.shutdown();       } catch (SchedulerException e) {           e.printStackTrace();       }   }}

以上就是Quartz 中Trigger的作用是什么,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

0