之前看了程序员杂志上关于spring 定时任务实现异步任务的文章,自己架了一套帮助实现一些费时的操作。
在实现中发现几个问题
1、定时任务中时间设置是这样的
<property name="delay" value="1000" /> <!-- 每次任务间隔 5秒--> <property name="period" value="5000" />
在某些配置下某任务开始后还没执行完过了5秒,第二个任务又起来了。
这与我的设计冲突。我希望任务是执行完后等5秒再进行第二个任务。
最后发现这个类可以
<bean id="springScheduleExecutorTask" class="org.springframework.scheduling.concurrent.ScheduledExecutorTask"> <!-- 配置主任务 --> <property name="runnable" ref="mainExecutor" /> <!-- 程序启动后延迟1秒执行第一次任务 --> <property name="delay" value="1000" /> <!-- 每次任务间隔 5秒--> <property name="period" value="5000" /> </bean>
2、在主任务中我把小任务分放给线程池操作,必须要等线程池完成工作后才能结束主任务run
如果起动线程池主任务run完毕,第二个任务5秒之后就运行了。我实现的代码是
//等待线程执行完毕 while(threadPool.getActiveCount() > 0){ try{ Thread.sleep(1000); }catch(Exception e){ e.printStackTrace(); } }
其实也可以采用观察者模式让线程池中任务发消息给主任务,主任务等待,
这个我之前有发给文章。 http://guoba6688-sina-com.iteye.com/blog/719972
附上所有代码
package com.my.task; import java.util.TimerTask; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * * 主任务起动 * * @author 锅巴 * @version 1.0 2010-7-29 */ public class MainExecutor extends TimerTask { private ThreadPoolTaskExecutor threadPool; @Override public void run() { // TODO Auto-generated method stub System.out.println("MainExecutor is start"); try{ Thread.sleep(5000); }catch(Exception e){ e.printStackTrace(); } threadPool.execute(new MyTask(10)); threadPool.execute(new MyTask(10)); threadPool.execute(new MyTask(10)); //等待线程执行完毕 while(threadPool.getActiveCount() > 0){ try{ Thread.sleep(1000); }catch(Exception e){ e.printStackTrace(); } } System.out.println("MainExecutor is end"); } public ThreadPoolTaskExecutor getThreadPool() { return threadPool; } public void setThreadPool(ThreadPoolTaskExecutor threadPool) { this.threadPool = threadPool; } public static void main(String[] args) { new ClassPathXmlApplicationContext(new String[]{"task.context.xml"}); } }
package com.my.task; public class MyTask implements Runnable{ private int count; public MyTask(int count){ this.count = count; } @Override public void run() { // TODO Auto-generated method stub for(int i=0; i<count; i++){ System.out.println(Thread.currentThread().getName() + " : " + i); } System.out.println(Thread.currentThread().getName() + " end "); } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "/spring-beans.dtd"> <beans default-autowire="byName"> <bean id="springScheduledExecutorFactoryBean" class="org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean"> <property name="scheduledExecutorTasks"> <list> <ref bean="springScheduleExecutorTask" /> </list> </property> </bean> <bean id="springScheduleExecutorTask" class="org.springframework.scheduling.concurrent.ScheduledExecutorTask"> <property name="runnable" ref="mainExecutor" /> <property name="delay" value="1000" /> <!-- 每次任务间隔 5秒--> <property name="period" value="5000" /> </bean> <!-- 主任务 负责扫描任务 将任务分配给线程完成 --> <bean id="mainExecutor" class="com.my.task.MainExecutor"> <property name="threadPool" ref="threadPool" /> </bean> <!-- 异步线程池 --> <bean id="threadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 核心线程数 --> <property name="corePoolSize" value="10" /> <!-- 最大线程数 --> <property name="maxPoolSize" value="50" /> <!-- 队列最大长度 >=mainExecutor.maxSize --> <property name="queueCapacity" value="1000" /> <!-- 线程池维护线程所允许的空闲时间 --> <property name="keepAliveSeconds" value="300" /> <!-- 线程池对拒绝任务(无线程可用)的处理策略 --> <property name="rejectedExecutionHandler"> <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/> </property> </bean> </beans>