文章标题:使用并发包线程池和XML实现定时任务动态配置和管理
文章地址: http://blog.csdn.net/5iasp/article/details/32705601
作者: javaboy2012
Email:[email protected]
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 博客大赛参赛文章,也欢迎大家投票和多多点击,有问题欢迎大家指出,互相交流,共同进步。