`

几年前写的一个任务调度模块

    博客分类:
  • Java
阅读更多
    大概是在09年下半年,参与了一个项目,当时项目有一些需要定期执行的任务,并且考虑到后续会有更多的任务需要调度,所以项目负责人决定做一个调度模块。而且,有了调度模块之后,其他项目可以重复利用,从而实现“一次编写处处可用”。这样,在有新的调度任务时,只要按照规则做一些简单的配置就可以了。最终,这个光荣的工作任务就落到了我手上。
 
    接下来说说调度模块的设计与实现思路。
 
从总体上,调度模块包括两部分:调度管理和调度执行引擎,这两部分独立部署,共用数据库。
 
一、调度管理
    调度管理主要是对任务、调度规则的配置管理。
 
1、支持的任务类型
1)URL
    可以指定需要定期调用的URL,同时可以配置相应的参数列表。这种方式,只要能通过URL进行访问的任务,都可以进行调度。
    优点:只要提供任务的URL,就可以进行调度,很灵活,配置简单。
    缺点:如果URL经过的网络比较差,调度时间稍有影响,但很细微;如果任务比较多或调度比较频繁,将会建议比较多的http连接,从设计上其实不太好。
 
2)存储过程
    可以指定需要定期调用的存储过程,同时可以配置存储过程的参数,但参数值是固定的。
 
3)实现调度任务接口方法
    系统定义了一个接口,该接口包含一个用于调度的方法。需要进行调度的任务,可以通过实现该接口,然后只要在调度管理模块进行类名全路径的简单配置,再配置调度规则,就可以实现对该任务的调度。
    另外,按照原来的设计思路,必须支持动态上传加载任务。即在项目上线运行过程中,不重启工程的情况下,可以通过上传class类、jar包任务代码,配置任务及调度规则之后,动态装载class类、jar包进行调度。
    优点:调度任务接口规范化了;动态装载任务的方式实现了任务的热装载,新增任务代码不需要重启工程。
    缺点:与使用URL的方式相比,自由度、灵活性稍差一些。
 
2、调度规则
    调度规则主要字段有:任务名称/代码、生效/失效日期、首次执行时间、任务类型(周期性/一次性)、每日(时、分、秒)/每周(周几、时、分、秒)/每月(几号、时、分、秒)、间隔(多少天/小时/分/秒)
 
二、调度执行引擎
    调度管理只是负责任务和规则的管理工作,实际的任务调度是由调度执行引擎负责实现。对任务的监测扫描,任务的启动、暂停、删除以及调度,都在这里实现。
 
    调度框架使用了比较流行的Quartz,结合Spring进行使用。其实当时还使用了另外一项批处理技术(spring batch),但事实上对于本部分的实现,它已经成了鸡肋。后来发现,去掉以后其实结构会更清晰,更易于维护。所以技术的东西,够用、适用就好了,太多太杂有时适得其反。
 
1、下面贴两张流程图
1)项目工程启动之后,调度任务的初始化过程


 
2)监测任务的工作过程


 
    监测任务每隔一段时间会调用一次,如10秒调用一次。
 
2、动态装载
1)动态状态类
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
    classLoader = ClassUtils.class.getClassLoader();
}
classLoader .loadClass(name);
 
2)动态状态装包中的类
URL url = new URL("file:" + jarPath); // jarPath为jar包的路径
URL[] urls = new URL[] {url};
URLClassLoader urlLoader = new URLClassLoader(urls, classLoader);
JarFile jarFile = new JarFile(new File(jarPath));
ZipEntry entry = jarFile.getEntry(jobNameFile); // jobNameFile中存放着所有要执行任务的类名全路径清单,按顺序存放
Scanner s = new Scanner(jarFile.getInputStream(entry));
while (s.hasNextLine()) {
    String name = s.nextLine().trim();
    Class<?> clazz = urlLoader.loadClass(name);
    ...
}
 
3、构造cron表达式
/**
 * 构造cron表达式
 */
public String getCronExpression(ExecPlan plan) {
	StringBuffer expression = null;
	if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_MONTH)) { // 每月
		expression = new StringBuffer();
		expression.append(plan.getFixedSeconds()).append(" ");
		expression.append(plan.getFixedMinutes()).append(" ");
		expression.append(plan.getFixedHours()).append(" ");
		expression.append(plan.getFixedDateNum()).append(" * ?");
	} else if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_WEEK)) { // 每周
		expression = new StringBuffer();
		expression.append(plan.getFixedSeconds()).append(" ");
		expression.append(plan.getFixedMinutes()).append(" ");
		expression.append(plan.getFixedHours()).append(" ? * ");
		expression.append(plan.getFixedDateNum());
	} else if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_DAY)) { // 每日
		expression = new StringBuffer();
		expression.append(plan.getFixedSeconds()).append(" ");
		expression.append(plan.getFixedMinutes()).append(" ");
		expression.append(plan.getFixedHours()).append(" * * ?");
	}
	return expression.toString();
}
 
 
 (转载请注明来源:http://zhanjia.iteye.com/blog/1870065)
  • 大小: 18.9 KB
  • 大小: 6.9 KB
8
6
分享到:
评论
4 楼 hersing 2013-06-03  
楼主在吗?像你咨询几个问题,现在项目中也用到了Quartz,现在我不明白的有几点,希望楼主有时间可以给我解惑。
1.启动工程时,初始化调度任务,我自己的代码是这样的:

public Scheduler scheduler;

/**
* 初始化
*/
public void initSchedule(){
try {
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}

List<DPScheduler> list=getAllScheduler();
for(DPScheduler dScheduler : list){
scheduleJob(dScheduler);
}
}

public void scheduleJob(DPScheduler dScheduler){
try {
JobDetail jobDetail=new JobDetail(dScheduler.getSchedulerNm(),scheduler.DEFAULT_GROUP,QuartzController.class);
CronTrigger ct = new CronTrigger(dScheduler.getSchedulerNm(),scheduler.DEFAULT_GROUP);
ct.setCronExpression(dScheduler.getProps());
ct.setStartTime(dScheduler.getBeginDate());
ct.setEndTime(dScheduler.getEndDate());
scheduler.scheduleJob(jobDetail, ct);
} catch (Exception e) {
e.printStackTrace();
}
}
我不明白的就是这个,一个scheduler的创建是通过SchedulerFactory来实现的,但是如果按照我的代码,至少说没有一个SchedulerFactory,这点不太明白。

2.其实这样的话,你自己配置的所有的scheduler已经准备就绪了,如果说再在页面中运行一个scheduler的话,其本质是否就是根据这个scheduler的ID去修改这个scheduler呢?

3.还希望楼主贴下初始化Scheduler的代码。感谢!
3 楼 javaboy2010 2013-05-24  
很不错啊! 能分享出代码吗?谢谢.
2 楼 zhanjia 2013-05-17  
Mybeautiful 写道
能不能分享下代码?

呵,有了思路之后,实现起来就容易多了。几年前的思路,不够完美,但基本够用。
这个属于公司项目的模块,不方便提供啊...
1 楼 Mybeautiful 2013-05-17  
能不能分享下代码?

相关推荐

    中心化的作业调度系统,定义了任务调度模型,实现了任务调度的统一管理和监控。.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    一个嵌入式牛人学习经历

    在后面的两年里我给自己定下了几个目标: 一.努力做好本职工作,在工作上得到公司和同事们的认同; 二.努力学习IC硬件设计知识,多向同事请教,并利用一切机会多实践; 三.实现我的实时操作系统的主要部分,完成TCP/...

    SpringBoot+Vue 企业级 智能通用报表 调度平台 管理系统.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    进程调度算法、内存管理算法、银行家算法(Java实现),可用于课设.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    《计算机操作系统》期末复习指导

    一般来说同步反映了进程之间的协作性质,往往指有几个进程共同完成一个任务时在时间次序上的某种限制,进程相互之间各自的存在及作用,通过交换信息完成通信。如接力比赛中一组队员使用接力棒等。 进程互斥...

    可重构制造系统的模块化和可转换特性:一种运维管理方法-研究论文

    为了使大规模生产受益并允许生产任何数量的高度定制产品,可重构制造系统(RMS)被视为未来几年的制造系统.RMS被定义为旨在满足零件族要求的系统通过Swift调整其硬件和软件组件以响应市场的突然变化。 RMS是最有...

    基于单片机的交通灯控制系统设计.doc

    图2 AT89C51最小系统 (2)指示灯模块 设计电路中每个路口的控制信号灯应有三个,即红灯、黄灯、绿灯各一个。因此,本 电路的设计中应用到红灯、黄灯、绿灯个四个。同一方向的两个路口的同一颜色指示灯 是同时亮灭...

    操作系统算法多语言实现.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    [removed]我喜欢称之为 ACNEScript 的 ECMAScript 的随机赔率和结尾......大声笑。 我从不这么称呼

    全局变量这是一个用于执行一般任务的所有小全局模块的存储桶......显然所有这些都在单独的脚本中,以确保任何使用它们的应用程序神奇地将您的浏览器变成一个在斜坡上运行的胖子。 负责任地使用。 连接并最小化。用户...

    Linker and loader

    允许使用模块(而不是一个单独的大文件)来构建程序的关键工具。 早在1947年,程序员们就开始使用原始的加载器:将程序的例程存储在多个不同的磁 带上,并将他们合并、重定位为一个程序。在上世纪60年代早期,这些...

    ARM 实验指导书第一册UCOS-II.doc

    从1998年4月,ARM上市之后,ARM在短短几年时间内已经成为一家全球性大公司,在三大洲8个国家都设有分支机构。ARM中国安谋咨询上海有限公司也已在2002年成立。目前,全世界由几十家著名的半导体公司都使用ARM公司的...

    RFID智能仓储方案规划.doc

    IC卡走过了十几年的历程 并得到了广泛的应用,但随着社会需求的不断扩大,要求更高,必将被新的技术所取代 ,这里所说的新技术就是射频识别技术(RFID)。 A.射频识别技术(RFID)的基本原理 RFID(Radio Frequency...

    Url重写篇视频------本讲将通过实例比较ASP.NET下的三种典型URL重写方案

    例如,如果我们写一个测试页面如下: Default.aspx Default.aspx.cs public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Response.Write...

    JAVA上百实例源码以及开源项目

     一个Java+ajax写的登录实例,附有JAVA源文件,JAVA新手朋友可以学习一下。 JAVA+JSP的聊天室 8个目标文件 简单 JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个...

    Hadoop实战中文版.PDF

    出版信息编辑译者:韩冀中出版社:人民邮电出版社出版时间:2011年10月版次:1.1开本:16开装帧:平装字数:417千字页数:253页内容简介编辑作为云计算所青睐的分布式架构,Hadoop是一个用Java语言实现的软件框架,...

    JAVA上百实例源码以及开源项目源代码

     一个Java+ajax写的登录实例,附有JAVA源文件,JAVA新手朋友可以学习一下。 JAVA+JSP的聊天室 8个目标文件 简单 JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个...

    Java范例开发大全 (源程序)

     实例1 开发第一个Java程序 7  第2章 Java基础类型与运算符(教学视频:39分钟) 9  2.1 基础类型 9  实例2 自动提升 9  实例3 自动转换 10  实例4 常用基础类型之强制转换 11  2.2 运算符 12  实例5...

    java范例开发大全(pdf&源码)

    实例1 开发第一个Java程序 7 第2章 Java基础类型与运算符(教学视频:39分钟) 9 2.1 基础类型 9 实例2 自动提升 9 实例3 自动转换 10 实例4 常用基础类型之强制转换 11 2.2 运算符 12 实例5 算术运算符 12 实例6 ...

    java范例开发大全源代码

     实例1 开发第一个Java程序 7  第2章 Java基础类型与运算符(教学视频:39分钟) 9  2.1 基础类型 9  实例2 自动提升 9  实例3 自动转换 10  实例4 常用基础类型之强制转换 11  2.2 运算符 12 ...

Global site tag (gtag.js) - Google Analytics