定时任务的Java实现
就是计划任务啦,只是在项目中这样叫也就习惯了,参考项目中大神的实现。
目的:通过MySQL配置,可以从MySQL中读取参数,按时定时启动和关闭。数据库记录字段包括实现类名(默认为jobName、jobGroupName、triggerName、triggerGroupName),创建时间,调度规则(cron表达式),启动标志,启动参数。
实现:quartz,与Strus2管理Action的思路相似(ActionMapping->ActionProxy->Action)。对于多节点的考虑,也是通过对数据库记录的查询、添加、删除实现Lock(数据库记录是唯一的)。
相关的类有5个
类 | 备注 |
---|---|
JobTimerController | 适配原有项目结构,启动调度器执行定时任务 |
JobScheduler | 静态调度器类,管理Job列表,对Job的CQUD操作 |
JobProxy | IJob的代理类,每个任务对应一个线程实例,执行定时任务 |
JobLock | 静态锁,防止多节点异步执行任务,基于数据库实现 |
IJob | 函数接口,定时任务需要基于此实现 |
类之间的关系如下
下面说说大体思路如何实现
1.定时任务调度器启动类JobTimerController
注意resultList、jobList只是保存Job的description(Map形式),但resultList是初始启动配置,jobList是内存中正运行的任务,而JobScheduler才是实际对IJob子类(相关任务实例)的操作(启动中断等)。因此,当数据库中添加了新的定时任务时,需要启动该类通知调度器类JobScheduler执行新的任务(本身该类该类也要当作定时任务执行才合理嘛)。
public void work(){
List resultList = /* 从数据库中获取任务 */
ArrayList jobList = JobScheduler.getJobList();
// 比较resultList与jobList
//调度器已经运行在内存中且已已有任务在执行
if (!ArrayUtils.isEmpty(jobList.toArray())){
for(int i=0;i<jobList.size();i++){
jobMap = (HashMap) jobList.get(i);
String jobName = jobMap.get("jobName").toString();
//resultList不存在,数据库中无记录则移除任务
if(!exist(jobName)){
//从quartz中删除,调用Scheduler.deleteJob
JobScheduler.removeJob(jobMap);
//从调度器JobScheduler中删除
jobList.remove(jobMap);
i--;
}
}
}
//配置好在数据库中,启动新的任务
if (!ArrayUtils.isEmpty(resultList.toArray())){
for(int i=0;i<resultList.size();i++){
jobMap = (HashMap) resultList.get(i);
String jobName = jobMap.get("jobName").toString();