Table of Contents
一、任务调度/定时任务
一个很火的开源任务调度框架,完全由Java
写成。Quartz
可以说是 Java 定时任务领域的老大哥或者说参考标准,其他的任务调度框架基本都是基于 Quartz
开发的,比如当当网的elastic-job
就是基于quartz
二次开发之后的分布式调度解决方案。
使用 Quartz
可以很方便地与 Spring
集成,并且支持动态添加任务和集群。但是,Quartz
使用起来也比较麻烦,API 繁琐。
并且,Quzrtz
并没有内置 UI 管理控制台,不过你可以使用 quartzui 这个开源项目来解决这个问题。
另外,Quartz
虽然也支持分布式任务。但是,它是在数据库层面,通过数据库的锁机制做的,有非常多的弊端比如系统侵入性严重、节点负载不均衡。有点伪分布式的味道。
优缺点总结:
- 优点: 可以与
Spring
集成,并且支持动态添加任务和集群。
- 缺点 :分布式支持不友好,没有内置 UI 管理控制台、使用麻烦(相比于其他同类型框架来说)
二、Quartz三大组件
-
任务 Job:即想要调用的任务类,需要实现org.quartz.job接口,并重写execute()方法,任务调度时会执行execute()方法。
-
触发器Trigger:即执行任务的触发器,当满足什么条件时会去执行你的任务Job,主要分为根据时长间隔执行的SimpleTrigger和根据日历执行的CronTrigger。
-
.调度器Scheduler:即将Trigger和Job绑定之后,根据Trigger中的设定,负责进行Job调度的组件。
一个调度器可以让多个触发器Trigger和任务Job绑定,而一个任务Job实例只能和一个触发器Trigger实例绑定,反过来也是如此。
三、Quartz 使用
1. 引入依赖
2. 定义任务
继承 QuartzJobBean 定义了两个任务:
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
|
package com.quartz.demo1.job;
import com.quartz.demo1.service.DemoService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.concurrent.atomic.AtomicInteger;
public class DemoJob01 extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(getClass());
private final AtomicInteger counts = new AtomicInteger();
@Autowired
private DemoService demoService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info(Thread.currentThread().getName() + ": execute a quartz01 job.");
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.quartz.demo1.job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class DemoJob02 extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info(Thread.currentThread().getName() + ": execute a quartz02 job.");
}
}
|
3. 配置Schedule:ScheduleConfiguration
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
61
|
package com.quartz.demo1.config;
import com.quartz.demo1.job.DemoJob01;
import com.quartz.demo1.job.DemoJob02;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ScheduleConfiguration {
public static class DemoJob01Configuration {
@Bean
public JobDetail demoJob01() {
return JobBuilder.newJob(DemoJob01.class)
.withIdentity("demoJob01") // 名字为 demoJob01
.storeDurably()
.build();
}
@Bean
public Trigger demoJob01Trigger() {
// 简单的调度计划的构造器
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(5) // 频率。
.repeatForever(); // 次数。
// Trigger 构造器
return TriggerBuilder.newTrigger()
.forJob(demoJob01()) // 对应 Job 为 demoJob01
.withIdentity("demoJob01Trigger") // 名字为 demoJob01Trigger
.withSchedule(scheduleBuilder) // 对应 Schedule 为 scheduleBuilder
.build();
}
}
public static class DemoJob02Configuration {
@Bean
public JobDetail demoJob02() {
return JobBuilder.newJob(DemoJob02.class)
.withIdentity("demoJob02") // 名字为 demoJob02
.storeDurably() // 没有 Trigger 关联的时候任务是否被保留。因为创建 JobDetail 时,还没 Trigger 指向它,所以需要设置为 true ,表示保留。
.build();
}
@Bean
public Trigger demoJob02Trigger() {
// 基于 Quartz Cron 表达式的调度计划的构造器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ? *");
// Trigger 构造器
return TriggerBuilder.newTrigger()
.forJob(demoJob02()) // 对应 Job 为 demoJob02
.withIdentity("demoJob02Trigger") // 名字为 demoJob02Trigger
.withSchedule(scheduleBuilder) // 对应 Schedule 为 scheduleBuilder
.build();
}
}
}
|
4. Application
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package com.quartz.demo1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}
|
Quartz快速入门
Spring Job、Quartz、XXL-Job 对比+全解析
定时任务JavaGuide