0%

Java定时任务调度工具Quartz

Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。

Quartz 核心概念

  1. Job 表示一个工作,要执行的具体内容。此接口中只有一个execute方法,如下:
    void execute(JobExecutionContext context)
  2. JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
  3. Trigger 代表一个调度参数的配置,什么时候去调。
  4. Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。

第一个Quartz程序

每隔两秒定时打印Hello World
HelloJob.java

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
package com.olliego;

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

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloJob
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前任务时间:" + sf.format(date));
System.out.println("Hello World");
}
}

HelloScheduler.java

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
package com.olliego;

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

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloScheduler
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {
//创建一个JobDetail实例,将该实例与HelloJob Class绑定,通过反射获取Job信息
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob", "group1").build();
//创建一个Trigger实例,定义该Job立即执行,并且两秒执行一次,直到永远
//虽然组名同为group1,但Trigger和JobDetail类不同,故不同组
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2).repeatForever())
.build();

//创建Scheduler实例
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();

//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + sf.format(date));

//将jobDetail和trigger绑定在一起,并传入到scheduler
scheduler.scheduleJob(jobDetail, trigger);
}
}

输出

1
2
3
4
5
6
7
当前时间:2020-06-21 11:17:13
当前任务时间:2020-06-21 11:17:13
Hello World
当前任务时间:2020-06-21 11:17:15
Hello World
当前任务时间:2020-06-21 11:17:17
Hello World

Job&JobDetail

Job实例在Quartz中的生命周期

每次调度器执行Job时,它在调用execute方法前会创建一个新的Job实例。
当调用完成后,关联的Job对象实例会被释放,释放的实例会被垃圾回收机制回收。

JobDetail

JobDetail为Job实例提供了许多设置属性,以及JobDataMap成员变量属性,它用来存储特定Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例。

重要属性

  • name 任务名称
  • group 任务所在的组
  • jobClass 任务的实现类
  • jobDataMap 可以用来装载任何可以序列化的数据对象,当Job实例对象被执行时这些参数对象会传递给它

JobExecutionContext

  • 当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法。
  • Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。

JobDataMap

JobDataMap简介

  • 在进行任务调度时JobDataMap存储在JobExecutionContext中,非常方便获取
  • JobDataMap可以用来装载任何可序列化的数据对象,当Job实例对象被执行时这些参数对象会传递给它。
  • JobDataMap实现了JDK的Map接口,并且添加了一些非常方便的方法用来存取基本数据类型。

JobDataMap获取方式一:从Map中直接获取

  • 分别获得JobDetail和Trigger下的JobDataMap

HelloJob.java

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
package com.olliego;

import org.quartz.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloJob
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前任务时间:" + sf.format(date));
JobKey key = jobExecutionContext.getJobDetail().getKey();
System.out.println("my job name and group are:" + key.getName() + ":"
+key.getGroup());
TriggerKey triggerKey = jobExecutionContext.getTrigger().getKey();
System.out.println("my trigger name and group are:" + triggerKey.getName() + ":"
+triggerKey.getGroup());

//分别获得JobDetail和Trigger下的JobDataMap
JobDataMap dataMap = jobExecutionContext.getJobDetail().getJobDataMap();
JobDataMap triggerDataMap = jobExecutionContext.getTrigger().getJobDataMap();
String jobMsg = dataMap.getString("message");
Float jobFloatValue = dataMap.getFloat("FloatJobValue");
String triggerMsg = triggerDataMap.getString("message");
Double triggerDoubleValue = triggerDataMap.getDouble("DoubleTriggerValue");

System.out.println("jobMsg:" + jobMsg);
System.out.println("jobFloatValue:" + jobFloatValue);
System.out.println("triggerMsg:" + triggerMsg);
System.out.println("triggerDoubleValue:" + triggerDoubleValue);

}
}

HelloScheduler.java

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
47
48
package com.olliego;

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

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloScheduler
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {
//创建一个JobDetail实例,将该实例与HelloJob Class绑定,通过反射获取Job信息
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob", "group1")
.usingJobData("message", "hello myJob1")
.usingJobData("FloatJobValue", 3.14F)
.build();
//创建一个Trigger实例,定义该Job立即执行,并且两秒执行一次,直到永远
//虽然组名同为group1,但Trigger和JobDetail类不同,故不同组
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.usingJobData("message", "hello myTrigger1")
.usingJobData("DoubleTriggerValue", 2.0D)
.startNow()
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2).repeatForever())
.build();

//创建Scheduler实例
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();

//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + sf.format(date));

//将jobDetail和trigger绑定在一起,并传入到scheduler
scheduler.scheduleJob(jobDetail, trigger);
}
}

输出

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
当前时间:2020-06-21 11:37:29
当前任务时间:2020-06-21 11:37:29
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobMsg:hello myJob1
jobFloatValue:3.14
triggerMsg:hello myTrigger1
triggerDoubleValue:2.0
当前任务时间:2020-06-21 11:37:31
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobMsg:hello myJob1
jobFloatValue:3.14
triggerMsg:hello myTrigger1
triggerDoubleValue:2.0
当前任务时间:2020-06-21 11:37:33
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobMsg:hello myJob1
jobFloatValue:3.14
triggerMsg:hello myTrigger1
triggerDoubleValue:2.0
当前任务时间:2020-06-21 11:37:35
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobMsg:hello myJob1
jobFloatValue:3.14
triggerMsg:hello myTrigger1
triggerDoubleValue:2.0
...
  • JobDataMap合并获取
    通过getMergedJobDataMap()合并Trigger和JobDetail的DataMap,相同名称数据Trigger覆盖JobDetail

HelloScheduler.java同上

HelloJob.java

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 com.olliego;

import org.quartz.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloJob
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前任务时间:" + sf.format(date));
JobKey key = jobExecutionContext.getJobDetail().getKey();
System.out.println("my job name and group are:" + key.getName() + ":"
+key.getGroup());
TriggerKey triggerKey = jobExecutionContext.getTrigger().getKey();
System.out.println("my trigger name and group are:" + triggerKey.getName() + ":"
+triggerKey.getGroup());

//合并之后的DataMap
JobDataMap dataMap = jobExecutionContext.getMergedJobDataMap();

String msg = dataMap.getString("message");
Float jobFloatValue = dataMap.getFloat("FloatJobValue");
Double triggerDoubleValue = dataMap.getDouble("DoubleTriggerValue");

System.out.println("jobFloatValue:" + jobFloatValue);
System.out.println("msg:" + msg);
System.out.println("triggerDoubleValue:" + triggerDoubleValue);

}
}

输出

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
当前时间:2020-06-21 18:08:25
当前任务时间:2020-06-21 18:08:25
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobFloatValue:3.14
msg:hello myTrigger1
triggerDoubleValue:2.0
当前任务时间:2020-06-21 18:08:27
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobFloatValue:3.14
msg:hello myTrigger1
triggerDoubleValue:2.0
当前任务时间:2020-06-21 18:08:29
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobFloatValue:3.14
msg:hello myTrigger1
triggerDoubleValue:2.0
当前任务时间:2020-06-21 18:08:31
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobFloatValue:3.14
msg:hello myTrigger1
triggerDoubleValue:2.0
...

JobDataMap获取方式二:从Map中直接获取

Job实现类中添加setter方法对应JobDataMap的键值(Quartz框架默认的JobFactory实现类在初始化Job实例对象时会自动地调用这些setter方法)

HelloScheduler.java同上

定义三个成员变量message、FloatJobValue、DoubleTriggerValue,名称与传入参数的key相同。
定义set方法,在生成Job实现类时通过反射调用set方法,对同名的成员变量进行赋值。
HelloJob.java

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.olliego;

import org.quartz.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloJob
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloJob implements Job {
private String message;
private Float FloatJobValue;
private Double DoubleTriggerValue;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public Float getFloatJobValue() {
return FloatJobValue;
}

public void setFloatJobValue(Float floatJobValue) {
FloatJobValue = floatJobValue;
}

public Double getDoubleTriggerValue() {
return DoubleTriggerValue;
}

public void setDoubleTriggerValue(Double doubleTriggerValue) {
DoubleTriggerValue = doubleTriggerValue;
}

@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前任务时间:" + sf.format(date));
JobKey key = jobExecutionContext.getJobDetail().getKey();
System.out.println("my job name and group are:" + key.getName() + ":"
+key.getGroup());
TriggerKey triggerKey = jobExecutionContext.getTrigger().getKey();
System.out.println("my trigger name and group are:" + triggerKey.getName() + ":"
+triggerKey.getGroup());

System.out.println("jobFloatValue:" + FloatJobValue);
System.out.println("msg:" + message);
System.out.println("triggerDoubleValue:" + DoubleTriggerValue);
}
}

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
当前时间:2020-06-21 18:40:15
当前任务时间:2020-06-21 18:40:15
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobFloatValue:3.14
msg:hello myTrigger1
triggerDoubleValue:2.0
当前任务时间:2020-06-21 18:40:17
my job name and group are:myJob:group1
my trigger name and group are:myTrigger:group1
jobFloatValue:3.14
msg:hello myTrigger1
triggerDoubleValue:2.0
...

Trigger

Quartz中的触发器,用来告诉调度程序作业什么时候触发。
即Trigger对象时是用来触发执行Job的。

触发器通用属性

  • JobKey
    表示Job实例的标识,触发器被触发时,该指定的Job实例会执行。
  • StartTime
    表示触发器的时间表首次被触发的时间。
    值的类型是Java.util.Date。
  • EndTime
    指定触发器的不再被触发的时间。
    值的类型是Java.util.Date。

HelloJob.java

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
47
48
49
50
51
52
53
54
55
56
57
package com.olliego;

import org.quartz.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloJob
*
* @author OllieGo
* @date 2020-06-24
*/
public class HelloJob implements Job {
private String message;
private Float FloatJobValue;
private Double DoubleTriggerValue;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public Float getFloatJobValue() {
return FloatJobValue;
}

public void setFloatJobValue(Float floatJobValue) {
FloatJobValue = floatJobValue;
}

public Double getDoubleTriggerValue() {
return DoubleTriggerValue;
}

public void setDoubleTriggerValue(Double doubleTriggerValue) {
DoubleTriggerValue = doubleTriggerValue;
}

@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前任务时间:" + sf.format(date));

Trigger currentTrigger = jobExecutionContext.getTrigger();
System.out.println("Start Time Is:" + sf.format(currentTrigger.getStartTime()));
System.out.println("End Time Is:" + sf.format(currentTrigger.getEndTime()));
JobKey jobKey = currentTrigger.getJobKey();
System.out.println("JobKey info---" + "jobName:" + jobKey.getName()
+ " jobGroup:" + jobKey.getGroup());
}
}

HelloScheduler.java

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
47
48
49
50
51
package com.olliego;

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

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloScheduler
*
* @author OllieGo
* @date 2020-06-24
*/
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {

//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + sf.format(date));

//创建一个JobDetail实例,将该实例与HelloJob Class绑定,通过反射获取Job信息
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob", "group1").build();
//获取当前时间3秒后的时间
date.setTime(date.getTime() + 3000);
//获取当前时间6秒后的时间
Date endDate = new Date();
endDate.setTime(endDate.getTime() + 6000);
//创建一个Trigger实例,定义该Job立即执行,并且两秒执行一次,直到永远
//虽然组名同为group1,但Trigger和JobDetail类不同,故不同组
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
.startAt(date)
.endAt(endDate)
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2).repeatForever())
.build();

//创建Scheduler实例
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();

//将jobDetail和trigger绑定在一起,并传入到scheduler
scheduler.scheduleJob(jobDetail, trigger);
}
}

输出

1
2
3
4
5
6
7
8
9
当前时间:2020-06-24 22:10:52
当前任务时间:2020-06-24 22:10:55
Start Time Is:2020-06-24 22:10:55
End Time Is:2020-06-24 22:10:58
JobKey info---jobName:myJob jobGroup:group1
当前任务时间:2020-06-24 22:10:57
Start Time Is:2020-06-24 22:10:55
End Time Is:2020-06-24 22:10:58
JobKey info---jobName:myJob jobGroup:group1

SimpleTrigger

  • SimpleTrigger的作用
    在一个 指定时间段执行一次 作业任务
    或是在 指定的时间间隔多次执行 作业任务

距离当前时间4秒后执行且仅执行一次任务

HelloJob.java

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
package com.olliego;

import org.quartz.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloJob
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloJob implements Job {

@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前任务时间:" + sf.format(date));
System.out.println("Hello world");
}
}

HelloScheduler.java

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
package com.olliego;

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

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloScheduler
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {

//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + sf.format(date));

//创建一个JobDetail实例,将该实例与HelloJob Class绑定,通过反射获取Job信息
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob").build();
//获取距离当前时间4秒后的具体时间
date.setTime(date.getTime() + 4000L);
//距离当前时间4秒后执行且仅执行一次任务
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
.startAt(date)
.build();

//创建Scheduler实例
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();

//将jobDetail和trigger绑定在一起,并传入到scheduler
scheduler.scheduleJob(jobDetail, trigger);
}
}

输出

1
2
3
当前时间:2020-06-25 12:01:21
当前任务时间:2020-06-25 12:01:25
Hello world

距离当前时间4秒后首次执行任务,之后每隔两秒重复执行一次任务

HelloJob.java

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
package com.olliego;

import org.quartz.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloJob
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloJob implements Job {

@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前任务时间:" + sf.format(date));
System.out.println("Hello world");
}
}

HelloScheduler.java

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
47
48
package com.olliego;

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

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloScheduler
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {

//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + sf.format(date));

//创建一个JobDetail实例,将该实例与HelloJob Class绑定,通过反射获取Job信息
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob").build();
//获取距离当前时间4秒后的具体时间
date.setTime(date.getTime() + 4000L);
//距离当前时间4秒后首次执行任务,之后每隔两秒重复执行一次任务
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
.startAt(date)
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2).withRepeatCount(
SimpleTrigger.REPEAT_INDEFINITELY
)
)
.build();
//创建Scheduler实例
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();

//将jobDetail和trigger绑定在一起,并传入到scheduler
scheduler.scheduleJob(jobDetail, trigger);
}
}

输出

1
2
3
4
5
6
7
8
9
10
当前时间:2020-06-25 13:07:41
当前任务时间:2020-06-25 13:07:45
Hello world
当前任务时间:2020-06-25 13:07:47
Hello world
当前任务时间:2020-06-25 13:07:49
Hello world
当前任务时间:2020-06-25 13:07:51
Hello world
...

CronTrigger

  • CronTrigger的作用

  • 基于日历* 的 作业调度器
    而不是像SimpleTrigger那样精确指定间隔时间,
    比SimpleTrigger更常用。

  • Cron表达式
    用于 配置CronTrigger 实例。
    是由 7个子表达式 组成的字符串,描述了时间表的详细信息。
    格式: 【秒】【分】【小时】【日】【月】【周】【年】

corn表达式字符

corn表达式举例

通配符说明

  • Cron表达式小提示
    ‘L’和’W’可以组合使用
    周字段英文字母不区分大小写,即MON与mon相同
    在线Cron表达式生成器,利用工具,在线生成

每秒执行一次任务
HelloJob.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.olliego;

import org.quartz.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloJob
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloJob implements Job {

@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前任务时间:" + sf.format(date));
System.out.println("Hello world");
}
}

HelloScheduler.java

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
package com.olliego;

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

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloScheduler
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {

//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + sf.format(date));

//创建一个JobDetail实例,将该实例与HelloJob Class绑定,通过反射获取Job信息
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob").build();
//每秒触发一次任务
CronTrigger trigger = (CronTrigger) TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
.withSchedule(
CronScheduleBuilder.cronSchedule("* * * * * ? *"))
.build();

//创建Scheduler实例
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();

//将jobDetail和trigger绑定在一起,并传入到scheduler
scheduler.scheduleJob(jobDetail, trigger);
}
}

输出

1
2
3
4
5
6
7
8
9
10
当前时间:2020-06-25 13:57:09
当前任务时间:2020-06-25 13:57:09
Hello world
当前任务时间:2020-06-25 13:57:10
Hello world
当前任务时间:2020-06-25 13:57:11
Hello world
当前任务时间:2020-06-25 13:57:12
Hello world
...

Scheduler

Scheduler-工厂模式
所有的Scheduler实例应该由SchedulerFactory来创建
SchedulerFactory包含StdSchedulerFactory和DirectSchedulerFactory

  • Quartz三个核心概念:
    调度器(Scheduler) 负责定期去执行Job
    任务(Job)需要实现的业务逻辑
    触发器(Trigger)告诉调度器何时执行指定好的任务

StdSchedulerFactory

  • 使用一组参数(Java.util.Properties)来创建和初始化Quartz调度器
  • 配置参数一般存储在quartz.properties中
  • 调用getScheduler方法就能创建和初始化调度器对象

StdSchedulerFactory的创建方式

1
2
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();

standby()表示scheduler挂起,可调用start()继续执行
shutdown(true)表示等待所有正在执行的job执行完毕之后,再关闭scheduler
shutdown(false)即shutdown(),表示直接关闭scheduler

HelloJob.java同上

HelloScheduler.java

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
47
48
49
50
51
52
53
54
55
56
package com.olliego;

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

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* HelloScheduler
*
* @author OllieGo
* @date 2020-06-21
*/
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException, InterruptedException {

//打印当前时间
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + sf.format(date));

//创建一个JobDetail实例,将该实例与HelloJob Class绑定,通过反射获取Job信息
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("myJob").build();
//每秒触发一次任务
CronTrigger trigger = (CronTrigger) TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
.withSchedule(
CronScheduleBuilder.cronSchedule("* * * * * ?"))
.build();

//创建Scheduler实例
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
scheduler.start();

System.out.println("scheduled time is:"
+ sf.format(scheduler.scheduleJob(jobDetail, trigger)));
//scheduler执行两秒后挂起,standby()
Thread.sleep(2000L);
scheduler.standby();

//scheduler执行三秒后继续执行
Thread.sleep(3000L);
scheduler.start();

Thread.sleep(3000L);
/**
* shutdown(true)表示等待所有正在执行的job执行完毕之后,再关闭scheduler
* shutdown(false)即shutdown(),表示直接关闭scheduler
*/
scheduler.shutdown(true);
}
}