文章标题:使用并发包线程池和XML实现定时任务动态配置和管理
文章地址: http://blog.csdn.net/5iasp/article/details/32705601
作者: javaboy2012
Email:yanek@163.com
qq: 1046011462
项目结构:
一、采用的知识点:
1. java并发包
2. xml配置文件读取
3. 反射动态调用类的方法
二、 基本思路
1. 创建线程池: ScheduledExecutorService scheduExec = Executors.newScheduledThreadPool(10);
2. 系统启动读取配置文件加载需要执行的任务列表。
List tasks=XmlReader.getTasks();
for (int i=0;i<tasks.size();i++)
{
TaskModel tm=(TaskModel)tasks.get(i);
scheduExec.scheduleAtFixedRate(new MyTask(tm),tm.getInitialDelay(), tm.getPeriod(), TimeUnit.SECONDS);
}
三 代码实现:
主要包括如下几个类和配置文件:
1. 启动类: Main类
package com.yanek.task;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
ScheduledExecutorService scheduExec = Executors.newScheduledThreadPool(10);
List tasks=XmlReader.getTasks();
for (int i=0;i<tasks.size();i++)
{
TaskModel tm=(TaskModel)tasks.get(i);
scheduExec.scheduleAtFixedRate(new MyTask(tm),tm.getInitialDelay(), tm.getPeriod(), TimeUnit.SECONDS);
}
}
}
2. MyTask类,实现Runable接口,线程池中调用
package com.yanek.task;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
public class MyTask implements Runnable {
private TaskModel taskModel;
public MyTask() {}
public MyTask(TaskModel tm) {
this.taskModel = tm;
}
public void run() {
System.out.println("call at " + (new Date()));
try {
Class<?> classType = Class.forName(taskModel.getClassName());
Method getMethod = classType.getMethod(taskModel.getMethodName());
getMethod.invoke(classType);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
其中使用到反射机制。
3. TaskModel类:任务配置的封装类
package com.yanek.task;
public class TaskModel {
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public long getInitialDelay() {
return initialDelay;
}
public void setInitialDelay(long initialDelay) {
this.initialDelay = initialDelay;
}
public long getPeriod() {
return period;
}
public void setPeriod(long period) {
this.period = period;
}
private String className;
private String methodName;
private long initialDelay;
private long period;
}
4. 任务配置文件: taskconfig.xml
例子如下:
<?xml version="1.0" encoding="UTF-8"?>
<taskconfig>
<task>
<class>com.yanek.task.TaskA</class>
<method>testA</method>
<initialDelay>5</initialDelay>
<period>2</period>
</task>
<task>
<class>com.yanek.task.TaskB</class>
<method>testB</method>
<initialDelay>5</initialDelay>
<period>3</period>
</task>
</taskconfig>
其中 一个元素<task>,对应一个类TaskModel的实例。配置包括需要线程池执行的类的名字,方法,和延迟执行的参数,重复执行的周期,
5. 具体需要执行的类:
TaskA类
TaskB类
package com.yanek.task;
public class TaskA {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("task a test");
}
public static void testA()
{
System.out.println("taska testA method call!");
}
}
package com.yanek.task;
public class TaskB {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("task b test");
}
public static void testB()
{
System.out.println("TaskB testB method call!");
}
}
6. XmlReader: 配置文件读取工具类
package com.yanek.task;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
public class XmlReader {
public static void main(String[] args) {
XmlReader.getTasks();
}
public static List getTasks() {
List tasks = new ArrayList();
System.out.println("load task config start...");
String path = "/work/TaskManager/conf/taskconfig.xml";
File file = new File(path);
if (file.exists() && !file.isDirectory()) {
try {
SAXBuilder sx = new SAXBuilder();
Document doc = sx.build(file);
Element rootelement = doc.getRootElement();
List<Element> childs = rootelement.getChildren();
for (int i = 0; i < childs.size(); i++) {
TaskModel tModel = new TaskModel();
tModel.setClassName(childs.get(i).getChildText("class"));
System.out.println(childs.get(i).getChildText("class"));
tModel.setMethodName(childs.get(i).getChildText("method"));
System.out.println(childs.get(i).getChildText("method"));
String initialDelay = childs.get(i).getChildText("initialDelay");
tModel.setInitialDelay((Long.valueOf(initialDelay)));
System.out.println("距离首次运行还差" + initialDelay + "秒!");
tModel.setPeriod(Integer.valueOf(childs.get(i).getChildText("period")));
System.out.println(childs.get(i).getChildText("period"));
tasks.add(tModel);
}
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println("file no exist!");
}
System.out.println("load task config end !");
return tasks;
}
}
四、测试执行:
执行Main类即可看到效果:
load task config start...
com.yanek.task.TaskA
testA
距离首次运行还差5秒!
2
com.yanek.task.TaskB
testB
距离首次运行还差5秒!
3
com.yanek.task.TaskC
testC
距离首次运行还差5秒!
3
load task config end !
call at Fri Jun 20 11:51:14 CST 2014
TaskB testB method call!
call at Fri Jun 20 11:51:14 CST 2014
call at Fri Jun 20 11:51:14 CST 2014
Taskc testC method call!
taska testA method call!
call at Fri Jun 20 11:51:16 CST 2014
taska testA method call!
call at Fri Jun 20 11:51:17 CST 2014
TaskB testB method call!
call at Fri Jun 20 11:51:17 CST 2014
Taskc testC method call!
五、使用方法:
1. 编写需要执行的类和方法,注意方法为静态方法,无返回值。
如下:
package com.yanek.task;
public class TaskC {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("task c test");
}
public static void testC()
{
System.out.println("Taskc testC method call! 具体的业务逻辑。");
}
}
2. 在配置文件中增加相应配置:
<task>
<class>com.yanek.task.TaskC</class>
<method>testC</method>
<initialDelay>5</initialDelay>
<period>3</period>
</task>
3. 启动Main类执行即可。
六、总结
该文章主要介绍了相关的任务调度和实现机制和全部代码,本身可以封装为一个简单的任务调度框架,简单实用,写个简单类和方法,配置到配置文件里就可以了。
希望对大家有所帮助,本文章为csdn 博客大赛参赛文章,也欢迎大家投票和多多点击,有问题欢迎大家指出,互相交流,共同进步。
使用Java并发包线程池和XML实现定时任务动态配置和管理,布布扣,bubuko.com
原文地址:http://blog.csdn.net/5iasp/article/details/32705601