Quartz学习笔记

image-20221127205106372

image-20221127213810488

image-20221128143023074

image-20221128130326946

image-20221128142414350

image-20221128142313901

quartz 总体架构

image-20221127223745383

Quartz的使用

导包

1
2
3
4
5
<!-- quartz -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

/**
* @author : 其然乐衣Letitbe
* @date : 2022/11/27
*/
public class MyJop implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("MyJob execute:" + new Date());
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package quartz.quartz;

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

/**
* @author : 其然乐衣Letitbe
* @date : 2022/11/27
*/
public class TestJob {
public static void main(String[] args) {
JobDetail jobDetail = JobBuilder.newJob(MyJop.class)
// name: 任务名称(在调度器里不能重复,唯一的) group : 组
.withIdentity("jop1", "group1")
.build();

// 触发器
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "trigger1")
.startNow()
// 时间间隔 永久重复执行
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever())
.build();

// 调度器
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail, trigger);
// 启动
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

运行结果图

image-20221127225021946


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
* @author : 其然乐衣Letitbe
* @date : 2022/11/27
*/
public class MyJop implements Job {

/**
* 如果在添加 .usingJobData("name", "trigger3") 的时候,
* key 和 这里定义的属性名一样的话,就会给这里的属性赋值,下面就可以直接用了
*/
private String name;

public void setName(String name) {
this.name = name;
}

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// System.out.println("MyJob execute:" + new Date());

JobDataMap jobDetailMap = context.getJobDetail().getJobDataMap();
JobDataMap triggerMap = context.getTrigger().getJobDataMap();
// 获取 JobDetail 和 Trigger 合并,但如果存在相同的键值key,Trigger的会覆盖JobDetail的
JobDataMap mergeMap = context.getMergedJobDataMap();

System.out.println("jobDetailMap:" + jobDetailMap.getString("job"));
System.out.println("triggerMap:" + triggerMap.getString("trigger"));
System.out.println("——————————————————————————————————————————————————————————————————————————");
System.out.println("mergeMap:" + mergeMap.getString("job"));
System.out.println("mergeMap:" + mergeMap.getString("trigger"));
System.out.println("——————————————————————————————————————————————————————————————————————————");
System.out.println( "name : " + name );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package quartz.quartz;

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

/**
* @author : 其然乐衣Letitbe
* @date : 2022/11/27
*/
public class TestJob {
public static void main(String[] args) {
JobDetail jobDetail = JobBuilder.newJob(MyJop.class)
// name: 任务名称(在调度器里不能重复,唯一的) group : 组
.withIdentity("jop1", "group1")
.usingJobData("job", "jobDetail1")
.usingJobData("name", "jobDetail2")
.build();

// 触发器
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "trigger1")
.usingJobData("trigger", "trigger")
// 会覆盖上面JobDetail中的name的值
.usingJobData("name", "trigger2")
.startNow()
// 时间间隔 永久重复执行
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever())
.build();

// 调度器
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail, trigger);
// 启动
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

结果

image-20221128103703359


Job : 封装成JobDetail设置属性

image-20221128132915669

image-20221128104234972

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import org.quartz.*;
import java.util.Date;

/**
* @DisallowConcurrentExecution : 禁止并发地执行通过一个 job 定义(JobDetail定义的)的多个实例
*/
@DisallowConcurrentExecution
public class MyJop implements Job {

/**
* 如果在添加 .usingJobData("name", "trigger3") 的时候,
* key 和 这里定义的属性名一样的话,就会给这里的属性赋值,下面就可以直接用了
*/
private String name;

public void setName(String name) {
this.name = name;
}

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {

// 会发现,不加注解的情况下(@DisallowConcurrentExecution)
// 下面的输出都是不一样的,证明不是同一个 Job 实例
System.out.println( "jobDetail : " + System.identityHashCode(context.getJobDetail()) );
System.out.println( "job : " + System.identityHashCode(context.getJobInstance()) );


// 不加上注解的话(@DisallowConcurrentExecution),
// 我们想着是每隔次启动 job 实例之后等待sleep 3秒 之后再重复启动的
// 但是实际发现,每隔一秒就又有启动了,证明不是同一个job实例,所以它们之间的启动不需要等待sleep的时间
System.out.println("execute : " + new Date());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

结果:

image-20221128110013728


测试count++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import org.quartz.*;

import java.util.Date;

/**
* @DisallowConcurrentExecution : 禁止并发地执行通过一个 job 定义(JobDetail定义的)的多个实例
*/
@DisallowConcurrentExecution
/**
* 持久化 JobDetail 中的 JobDataMap (对 trigger 中的 datamap 无效)
* 如果一个任务不是持久化的,则当没有触发器关联它的时候,Quartz会从scheduler中删除它
*/
@PersistJobDataAfterExecution
public class MyJop implements Job {

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {

JobDataMap triggerMap = context.getTrigger().getJobDataMap();
JobDataMap jobDetailMap = context.getJobDetail().getJobDataMap();
triggerMap.put("count", triggerMap.getInt("count") + 1);
jobDetailMap.put("count1", jobDetailMap.getInt("count1") + 1);
System.out.println( "triggerMap count : " + triggerMap.getInt("count") );
System.out.println( "jobDetailMap count : " + jobDetailMap.getInt("count1") );

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

/**
* @author : 其然乐衣Letitbe
* @date : 2022/11/27
*/
public class TestJob {
public static void main(String[] args) {
JobDetail jobDetail = JobBuilder.newJob(MyJop.class)
// name: 任务名称(在调度器里不能重复,唯一的) group : 组
.withIdentity("jop1", "group1")
.usingJobData("job", "jobDetail1")
.usingJobData("name", "jobDetail2")
.usingJobData("count1", 0)
.build();

int count = 0;

// 触发器
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "trigger1")
.usingJobData("trigger", "trigger")
// 会覆盖上面JobDetail中的name的值
.usingJobData("name", "trigger2")
.usingJobData("count", count)
.startNow()
// 时间间隔 永久重复执行
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever())
.build();

// 调度器
try {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail, trigger);
// 启动
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

结果图:

image-20221128132552340

Springboot整合Quartz

image-20221128143743504

Springboot整合Quartz

使用Springboot里面的监听器,让项目在启动后也启动了调度器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package quartz.bootquartz;

import org.quartz.*;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.Date;

/**
* @author : 其然乐衣Letitbe
* @date : 2022/11/28
*/

/**
* @DisallowConcurrentExecution : 禁止并发地执行通过一个 job 定义(JobDetail定义的)的多个实例
*/
@DisallowConcurrentExecution
/**
* 持久化 JobDetail 中的 JobDataMap (对 trigger 中的 datamap 无效)
* 如果一个任务不是持久化的,则当没有触发器关联它的时候,Quartz会从scheduler中删除它
*/
@PersistJobDataAfterExecution
public class QuartzJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
Thread.sleep(2000);
System.out.println(context.getScheduler().getSchedulerInstanceId());

System.out.println("taskname : " + context.getJobDetail().getKey().getName() );
System.out.println("执行时间 :" + new Date());
} catch (Exception e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package quartz.bootquartz;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @author : 其然乐衣Letitbe
* @date : 2022/11/28
*/
@Configuration
public class SchedulerConfig {

@Bean
public Scheduler scheduler() {
Scheduler scheduler1 = null;
try {
scheduler1 = StdSchedulerFactory.getDefaultScheduler();
} catch (SchedulerException e) {
e.printStackTrace();
}
return scheduler1;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package quartz.bootquartz.listener;

import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import quartz.bootquartz.QuartzJob;

/**
* @author : 其然乐衣Letitbe
* @date : 2022/11/28
*/
@Component
public class StartApplicationListener implements ApplicationListener<ContextRefreshedEvent> {

/**
* 注入调度器
*/
@Autowired
private Scheduler scheduler;

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
TriggerKey triggerKey = TriggerKey.triggerKey("trigger1", "group1");
try {
Trigger trigger = scheduler.getTrigger(triggerKey);
if (trigger == null) {
trigger = TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
.startNow()
.build();
JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class)
.withIdentity("job1", "group1")
.build();

scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
} catch (SchedulerException e) {
e.printStackTrace();
}

}
}

结果:

image-20221128152834236

image-20221217151142631