目录
  1. 1. 前言
    1. 1.1. 简单介绍–Quartz
    2. 1.2. 使用–Quartz
    3. 1.3. 工具分享–Quartz
    4. 1.4. 小结–Quartz
Java定时任务Quartz的使用

前言

开发微信推送的时候遇到需要定时向公众号推送满意度调查问卷,由于这些都是需要可配置的,所以我就找了找有没有可用的Java定时任务组件,Quartz这个刚好满足我的需要。现在将我使用的一些心得以及使用的工具类分享给大家!

简单介绍–Quartz


Quartz是由Java编写作业调度框架,在应用程序中进行作业调度提供了非常实用的机制。Quartz允许开发人员根据时间间隔(可以自定义时间表达式)来调度作业。它实现了任务和触发器的多对多的关系。
下面简单的介绍下我们会使用到的几个类!

org.quartz.Job
它是一个抽象接口,表示一个工作,也就是我们要执行的具体内容,重要方法:
void execute(JobExecutionContext context) ;
实现这个接口将要完成的任务业务逻辑填充在这里面。
org.quartz.JobDetail
表示具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容,它包含了这个任务调度的方案和策略。
org.quartz.CronTrigger
表示一个调度参数的配置,通过定义和配置这个触发器,来告诉调度容器什么时候去调用JobDetail。由我们自定义的时间表达式来告诉程序我们什么时候去执行这个任务。
org.quartz.Scheduler
调度的容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了。重要方法:
void shutdown(); //停止这个任务 若传入true表示执行完这个任务再停止
void start(); //开始任务

使用–Quartz


  1. 动态作业的实现:由于JobDetail、CronTrigger我们是可以在运行时重新设置的,而且是在下次调用时候起作用。所以我们完全可以通过代码动态的配置我们程序的任务(当然前提是有这个需求哈!),可以将调度方案存在到配置文件(或是数据库)中,然后动态的加载这些任务。
  2. JobDetail不存储具体的实例,使用时我们需要定义一个他的实例,同时它又指向JobDataMap。 JobDetail里面有Job的详细信息,如它所属的组,名称等信息。
  3. JobDataMap里面存放着Job实例的对象,并保持着他们的信息,它是Map接口的实现,可以往里面添加和移除要存储的信息.
  4. Scheduler调度容器包含多个JobDetail和CronTrigger。Scheduler是个调度容器,里面有一个线程池,用来并行调度执行每个作业,这样可以提高调用的效率。
  5. 基本使用流程

    调度器线程运行run() ==> 获取待触发trigger (读取JobDetail信息,读取trigger表中触发器信息标记为”已获取”) ==> 触发trigger (确认trigger的状态,读取trigger的JobDetail信息 ,读取trigger的Calendar信息 ,更新trigger信息) ==> 实例化并执行Job (从线程池获取线程执行JobRunShell的run方法)

示例

初始化一个调度容器,从工厂类获取实例

1
SchedulerFactory sf = new StdSchedulerFactory();
2
Scheduler sch = sf.getScheduler();

定义我们自己的任务

1
JobDetail jobDetail = new JobDetail(jobName, DEFAULT_JOB_GROUP_NAME, doClass);//具体任务,参数: 任务名,任务分组,任务执行类

定义触发器

1
CronTrigger trigger = new CronTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME);   //时间触发器,参数: 触发器名,触发器组
2
trigger.setCronExpression(time);

将任务和触发器添加到调度容器

1
sched.scheduleJob(jobDetail, trigger);

启动任务

1
if (!sched.isShutdown()) {
2
	sched.start();
3
}

工具分享–Quartz


工具类对于开发来讲是必不可少的,我相信有的人可能就直接跳过上面的内容直接来这边复制工具类了,不过我还是建议大家看下上面的内容,加深下对于Quartz整体的一个了解!话不多说,下面就是我所使用的工具类

1
import org.quartz.CronTrigger;
2
import org.quartz.JobDetail;
3
import org.quartz.Scheduler;
4
import org.quartz.SchedulerFactory;
5
import org.quartz.impl.StdSchedulerFactory;
6
7
/**
8
 * @Description: 定时任务管理类
9
 * @ClassName: QuartzJobManager
10
 * @author hjf
11
 * @date 2017-06-30
12
 */
13
public class QuartzJobManager {
14
	
15
	private static SchedulerFactory mySchedulerFactory = new StdSchedulerFactory();
16
	//统一任务分组名
17
	private static String DEFAULT_JOB_GROUP_NAME = "DEFAULT";
18
	//统一触发器分组名
19
	private static String DEFAULT_TRIGGER_GROUP_NAME = Scheduler.DEFAULT_GROUP;
20
21
	/**
22
	 * @Description: 默认添加一个定时任务
23
	 * @param jobName  任务名
24
	 * @param doClass      任务
25
	 * @param time     时间设置,参考quartz说明文档
26
	 * @author hjf
27
	 * @date 2017-06-30
28
	 */
29
	@SuppressWarnings({ "rawtypes" })
30
	public static void addJob(String jobName, Class doClass, String time) {
31
		try {
32
			//从工厂获取一个调度
33
			Scheduler sched = mySchedulerFactory.getScheduler();
34
			JobDetail jobDetail = new JobDetail(jobName, DEFAULT_JOB_GROUP_NAME, doClass);//具体任务,参数: 任务名,任务分组,任务执行类
35
			CronTrigger trigger = new CronTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME);   //时间触发器,参数: 触发器名,触发器组
36
			trigger.setCronExpression(time);   //触发器时间设定(时间表达式)
37
			sched.scheduleJob(jobDetail, trigger);  //将任务详情和时间情况添加到调度
38
			
39
			//启动
40
			if (!sched.isShutdown()) {
41
				sched.start();
42
			}
43
		} catch (Exception e) {
44
			throw new RuntimeException(e);
45
		}
46
	}
47
48
	/**
49
	 * @Description: 自定义添加一个定时任务
50
	 * @param jobName       任务名
51
	 * @param jobGroupName  任务组名
52
	 * @param triggerName   触发器名
53
	 * @param triggerGroupName  触发器组名
54
	 * @param doClass 任务
55
	 * @param time     时间设置,参考quartz说明文档
56
	 * @author hjf
57
	 * @date 2017-06-30 
58
	 */
59
	@SuppressWarnings("rawtypes")
60
	public static void addJob(String jobName, String jobGroupName,
61
			String triggerName, String triggerGroupName, Class doClass,
62
			String time) {
63
		try {
64
			//从工厂获取一个调度
65
			Scheduler sched = mySchedulerFactory.getScheduler();
66
			JobDetail jobDetail = new JobDetail(jobName, jobGroupName, doClass);//具体任务,参数: 任务名,任务分组,任务执行类
67
			CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);//时间触发器,参数: 触发器名,触发器组
68
			trigger.setCronExpression(time);//触发器时间设定(时间表达式)
69
			sched.scheduleJob(jobDetail, trigger);//将任务详情和时间情况添加到调度
70
			
71
			//启动
72
			if (!sched.isShutdown()) {
73
				sched.start();
74
			}
75
		} catch (Exception e) {
76
			throw new RuntimeException(e);
77
		}
78
	}
79
80
	/**
81
	 * @Description: 修改一个任务的触发时间
82
	 * 先移除原来旧的job再添加新的job
83
	 * @param jobName  任务名
84
	 * @param time     时间表达式
85
	 * @author hjf
86
	 * @date 2017-06-30 
87
	 */
88
	@SuppressWarnings("rawtypes")
89
	public static void modifyJobTime(String jobName, String time) {
90
		try {
91
			Scheduler sched = mySchedulerFactory.getScheduler();
92
			CronTrigger trigger = (CronTrigger) sched.getTrigger(jobName,DEFAULT_TRIGGER_GROUP_NAME);
93
			if (trigger == null) {
94
				return;
95
			}
96
			String oldTime = trigger.getCronExpression();  //获取旧的时间表达式
97
			if (!oldTime.equalsIgnoreCase(time)) {
98
				JobDetail jobDetail = sched.getJobDetail(jobName,DEFAULT_JOB_GROUP_NAME);  //获取任务详情
99
				Class objJobClass = jobDetail.getJobClass();
100
				removeJob(jobName);                 //移除旧任务
101
				addJob(jobName, objJobClass, time); //添加新的任务
102
			}
103
		} catch (Exception e) {
104
			throw new RuntimeException(e);
105
		}
106
	}
107
108
	/**
109
	 * @Description: 修改一个任务的触发时间
110
	 * @param triggerName        触发器名称
111
	 * @param triggerGroupName   触发器组名
112
	 * @param time               时间表达式
113
	 * @author hjf
114
	 * @date 2017-06-30 
115
	 */
116
	public static void modifyJobTime(String triggerName,String triggerGroupName, String time) {
117
		try {
118
			Scheduler sched = mySchedulerFactory.getScheduler();
119
			CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerName,triggerGroupName);
120
			if (trigger == null) {
121
				return;
122
			}
123
			//获取旧的时间表达式
124
			String oldTime = trigger.getCronExpression();  
125
			if (!oldTime.equalsIgnoreCase(time)) {
126
				CronTrigger ct = (CronTrigger) trigger;
127
				// 修改时间
128
				ct.setCronExpression(time);
129
				// 重启触发器
130
				sched.resumeTrigger(triggerName, triggerGroupName);
131
			}
132
		} catch (Exception e) {
133
			throw new RuntimeException(e);
134
		}
135
	}
136
137
	/**
138
	 * @Description: 移除一个任务  使用默认配置
139
	 * @param jobName   任务名
140
	 * @author hjf
141
	 * @date 2017-06-30 
142
	 */
143
	public static void removeJob(String jobName) {
144
		try {
145
			Scheduler sched = mySchedulerFactory.getScheduler();
146
			sched.pauseTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME);  // 停止触发器
147
			sched.unscheduleJob(jobName, DEFAULT_TRIGGER_GROUP_NAME); // 移除触发器
148
			sched.deleteJob(jobName, DEFAULT_JOB_GROUP_NAME);         // 删除任务
149
		} catch (Exception e) {
150
			throw new RuntimeException(e);
151
		}
152
	}
153
154
	/**
155
	 * @Description:  移除一个任务   自定义配置
156
	 * @param jobName               任务名
157
	 * @param jobGroupName 			任务组名
158
	 * @param triggerName			触发器名
159
	 * @param triggerGroupName		触发器组名
160
	 * @author hjf
161
	 * @date 2017-06-30 
162
	 */
163
	public static void removeJob(String jobName, String jobGroupName,String triggerName, String triggerGroupName) {
164
		try {
165
			Scheduler sched = mySchedulerFactory.getScheduler();
166
			sched.pauseTrigger(triggerName, triggerGroupName);      // 停止触发器
167
			sched.unscheduleJob(triggerName, triggerGroupName);		// 移除触发器
168
			sched.deleteJob(jobName, jobGroupName);					// 删除任务
169
		} catch (Exception e) {
170
			throw new RuntimeException(e);
171
		}
172
	}
173
174
	/**
175
	 * @Description:启动定时的任务
176
	 * @author hjf
177
	 * @date 2017-06-30 
178
	 */
179
	public static void startJobs() {
180
		try {
181
			Scheduler sched = mySchedulerFactory.getScheduler();
182
			sched.start();
183
		} catch (Exception e) {
184
			throw new RuntimeException(e);
185
		}
186
	}
187
188
	/**
189
	 * @Description:关闭定时任务
190
	 * @author hjf
191
	 * @date 2017-06-30 
192
	 */
193
	public static void shutdownJobs() {
194
		try {
195
			Scheduler sched = mySchedulerFactory.getScheduler();
196
			if (!sched.isShutdown()) {
197
				sched.shutdown();
198
			}
199
		} catch (Exception e) {
200
			throw new RuntimeException(e);
201
		}
202
	}
203
}

小结–Quartz


对于Quartz的基本使用就是这些内容了,关于时间表达示以及Quartz运行机制的分析可能会在后面的博文中给出(不过这个博主有点懒啊,希望大家多多支持,您的支持就是对我最大的鼓励)。
谢谢大家的支持,转载请注明出处!

文章作者: 黄建峰
文章链接: http://missxhh.com/posts/b5390ddf/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 黄建峰

评论