其他分享
首页 > 其他分享> > quartz(二)

quartz(二)

作者:互联网

quartz(二)

通过官网案例,我们会有个疑惑,

  1. 为什么调度器(Scheduler)不直接调度任务(Job),而是由触发器(Trigger)去调度呢?是否可以在调度器直接指定一个规则直接调度job呢?

  2. 根据官网提供的案例,一共有四个名称指令,为什么会设计的这么麻烦?

首先回答第一个问题,既然任务是由Trigger触发,而不是Scheduler直接调度,那是否可以认为,一个任务可以有多个Trigger触发呢?下面通过代码演示验证我们的猜想.

根据上一篇的demo,我i们稍微改变一下代码,新增了一个Trigger

public class QuartzTest {
​
    public static void main(String[] args) {
​
        try {
​
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
​
            scheduler.start();
​
            JobDetail job = JobBuilder.newJob(HelloJob.class)
                    .withIdentity("job1", "group1")
                    .build();
            // 0 1 2 3
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger1", "group1")
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(1)
                            .repeatForever())
                    .build();
            //0 1
            Trigger trigger2 = TriggerBuilder.newTrigger()
                    .withIdentity("trigger2", "group2")
                    .forJob("job1", "group1")
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(3)
                            .repeatForever())
                    .build();
​
            scheduler.scheduleJob(job, trigger);
            scheduler.scheduleJob(trigger2);
​
            TimeUnit.SECONDS.sleep(3);
            scheduler.shutdown();
​
        } catch (Exception se) {
            se.printStackTrace();
        }
    }
}
​

trigger2会比trigger多一个forJob(),这么做是因为,我们在调度任务的时候,并不是每次都能拿到job这个对象的,所以增加forJob()指定从而触发这个job.

运行结果:

​
Hello.execute!!!2022.05.29 11:00:01 DefaultQuartzScheduler_Worker-2
Hello.execute!!!2022.05.29 11:00:01 DefaultQuartzScheduler_Worker-1
Hello.execute!!!2022.05.29 11:00:02 DefaultQuartzScheduler_Worker-3
Hello.execute!!!2022.05.29 11:00:03 DefaultQuartzScheduler_Worker-4
Hello.execute!!!2022.05.29 11:00:04 DefaultQuartzScheduler_Worker-5
Hello.execute!!!2022.05.29 11:00:04 DefaultQuartzScheduler_Worker-6
​
BUILD SUCCESSFUL in 5s
​
​

通过运行结果,我们发现,跑了很标准的6次,那我们怎么确定第一个Trigger跑了4次,第二个Trigger跑了2次呢?

此时我们修改一下HelloJob

public class HelloJob implements Job {
​
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
​
        StringJoiner stringJoiner = new StringJoiner("")
                .add("Hello.execute!!!")
                .add(DFUtil.format(new Date()))
                .add(Thread.currentThread().getName())
                .add(context.getTrigger().getKey().getName());
​
        System.out.println(stringJoiner);
    }
}

再次执行查看打印结果

Hello.execute!!!2022.05.29 11:05:06DefaultQuartzScheduler_Worker-2trigger2
Hello.execute!!!2022.05.29 11:05:06DefaultQuartzScheduler_Worker-1trigger1
Hello.execute!!!2022.05.29 11:05:07DefaultQuartzScheduler_Worker-3trigger1
Hello.execute!!!2022.05.29 11:05:08DefaultQuartzScheduler_Worker-4trigger1
Hello.execute!!!2022.05.29 11:05:09DefaultQuartzScheduler_Worker-5trigger1
Hello.execute!!!2022.05.29 11:05:09DefaultQuartzScheduler_Worker-6trigger2
​
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
​
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
​
See https://docs.gradle.org/7.4.1/userguide/command_line_interface.html#sec:command_line_warnings
​
BUILD SUCCESSFUL in 5s

此时可以验证两个Trigger执行的次数;

那么此时的模型则变为了

一个Scheduler可以调度多个Trigger

那新的问题产生了,一个Trigger是否可以触发多个Job呢?

根据官方文档描述: Many Triggers can point to the same Job, but a single Trigger can only point to one Job

我们知道,一个Job可以被多个Trigger 触发,但是一个Trigger 只能触发一个Job;


下面解决第二个问题,关于JobDetail和Trigger的name和group;

首先,group是用来标记,方便管理的;name是用来标记的,既然name和group都是用来标记的,那也可以只用name去做标记就好了,看一下源码

 

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

当我们把name和group设置为null时,

    public Key(String name, String group) {
        if(name == null)
            throw new IllegalArgumentException("Name cannot be null.");
        this.name = name;
        if(group != null)
            this.group = group;
        else
            this.group = DEFAULT_GROUP;
    }
    
    public static final String DEFAULT_GROUP = "DEFAULT";

此时我们发现,就算group设置为null,它也会默认传一个DEFAULT,这么做是为了什么呢?

Scheduler调度Trigger时有一个方法:scheduler.pauseJobs();它里面需要传入group组名,如果不传入,那么这一组任务就会暂停


Trigger的name和group明白了之后,我们看一下JobDetail的name和group的作用

我们可以试想这样的一个问题,根据官方文档说明,一个Job可以被多个Trigger触发,那么一个Job可不可以被多个Jobdetail引用呢?

我们再来修改一下代码,让Trigger触发Job,Trigger2触发Job2

public class QuartzTest3 {
​
    public static void main(String[] args) {
​
        try {
​
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
​
            scheduler.start();
​
            JobDetail job = JobBuilder.newJob(HelloJob.class)
                    .withIdentity("job1", "group1")
                    .build();
​
            JobDetail job2 = JobBuilder.newJob(HelloJob.class)
                    .withIdentity("job2", "group1")
                    .build();
​
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger1", "group1")
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(1)
                            .repeatForever())
                    .build();
​
            Trigger trigger2 = TriggerBuilder.newTrigger()
                    .withIdentity("trigger2", "group2")
                    .forJob("job2", "group1")
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(3)
                            .repeatForever())
                    .build();
​
            scheduler.scheduleJob(job, trigger);
            scheduler.scheduleJob(job2,trigger2);
​
            TimeUnit.SECONDS.sleep(3);
            scheduler.shutdown();
​
        } catch (Exception se) {
            se.printStackTrace();
        }
    }
}

运行结果

Hello.execute!!!2022.05.29 11:33:12DefaultQuartzScheduler_Worker-1trigger1
Hello.execute!!!2022.05.29 11:33:12DefaultQuartzScheduler_Worker-2trigger2
Hello.execute!!!2022.05.29 11:33:13DefaultQuartzScheduler_Worker-3trigger1
Hello.execute!!!2022.05.29 11:33:14DefaultQuartzScheduler_Worker-4trigger1
Hello.execute!!!2022.05.29 11:33:15DefaultQuartzScheduler_Worker-5trigger1
Hello.execute!!!2022.05.29 11:33:15DefaultQuartzScheduler_Worker-6trigger2
​
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
​
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
​
See https://docs.gradle.org/7.4.1/userguide/command_line_interface.html#sec:command_line_warnings
​
BUILD SUCCESSFUL in 7s

通过代码结果,我们可以判定,quartz的真实模型如下

综上,我们可以获知:一个Job可以被多个Trigger 触发,但是一个Trigger 只能触发一个Job;一个Job可以被多个JobDetail所关联,不过我们在实际使用过程中,一个Job并不会被多个JobDetail所关联;实际生产中,还是以一个Job可以被多个Trigger 触发,一个JobDaetail只关联一个Job;因为生产过程中,不仅仅是自动触发任务,还需要手动去触发任务;

我们再次修改代码,将四个标记全部注释掉

public class QuartzTest4 {
​
    public static void main(String[] args) {
​
        try {
​
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
​
            scheduler.start();
​
            JobDetail job = JobBuilder.newJob(HelloJob.class)
//                    .withIdentity("job1", "group1")
                    .build();
​
            Trigger trigger = TriggerBuilder.newTrigger()
//                    .withIdentity("trigger1", "group1")
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule() 
                            .withIntervalInSeconds(1)
                            .repeatForever())
                    .build();
​
            scheduler.scheduleJob(job, trigger);
​
            TimeUnit.SECONDS.sleep(3);
            scheduler.shutdown();
​
        } catch (Exception se) {
            se.printStackTrace();
        }
    }
}
​

运行结果

Hello.execute!!!2022.05.29 11:43:36DefaultQuartzScheduler_Worker-16da64b5bd2ee-f5a2f797-524c-44ab-802e-3833ccbc6433
Hello.execute!!!2022.05.29 11:43:37DefaultQuartzScheduler_Worker-26da64b5bd2ee-f5a2f797-524c-44ab-802e-3833ccbc6433
Hello.execute!!!2022.05.29 11:43:38DefaultQuartzScheduler_Worker-36da64b5bd2ee-f5a2f797-524c-44ab-802e-3833ccbc6433
Hello.execute!!!2022.05.29 11:43:39DefaultQuartzScheduler_Worker-46da64b5bd2ee-f5a2f797-524c-44ab-802e-3833ccbc6433
​
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
​
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
​
See https://docs.gradle.org/7.4.1/userguide/command_line_interface.html#sec:command_line_warnings
​
BUILD SUCCESSFUL in 8s

随机生成了一个MD5的name值;

标签:execute,quartz,Worker,29,Trigger,2022.05,Hello
来源: https://www.cnblogs.com/wangshaoyun/p/16325375.html