现在的位置: 首页 > 综合 > 正文

Jdk自带的定时任务TimerTask和ScheduledExecutorService及其在Spring中的集成

2012年08月17日 ⁄ 综合 ⁄ 共 2620字 ⁄ 字号 评论关闭

1,java.util.Timer和TimerTask是JDK1.3自带的定时任务实现类,使用非常简单,不过由于依赖系统时间,在时间跳变的情况下,执行会出现一些变化。如果时间向后(未来方向)修改,不影响任务执行,但如果向前(过去方向)修改,取决于时间调整的幅度,定时任务可能延迟很久才能回复正常,这在程序运行过程中,可能并不是我们所期望的的,对于一些依赖定时任务执行的关键任务 ,可能导致严重后果。

 

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		TimerTask task = new TimerTask()
		{
			public void run() 
			{
				System.out.println("Timer task execute " + ++times + " at " + new Date() + 
						",expected executing at " +  new Date(this.scheduledExecutionTime()));
			}
		};
		
		Timer tm = new Timer();
		/**
		 * Timer基于系统时间是准确的前提;执行过程中:
		 * 如果系统时间被往后修改,根据Timer类mainLoop方法中taskFired = (executionTime<=currentTime)的判断,程序还是会继续执行,间隔也不受影响
		 * 如果系统时间被往前修改,仍然是根据上面所述判断,则下一次执行时间会被延后,后面恢复正常
		 */
		tm.schedule(task, new Date(), 2 * 60 * 1000);
	}

  

2,自打JDK1.5开始,我们可以选择ScheduledExecutorService来替代Timer执行定时任务。ScheduledExecutorService并不是基于绝对的时间和周期,而是基于时间延迟和周期,这样当出现时间跳变(网络延迟/时间服务器同步/人工干预修改时间),定时任务仍然按照原来的时间间隔执行。

public class JdkScheduledExecutorService
{
	private static int times = 0;
	private static long nextExecuteTime = new Date().getTime();

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		TimerTask task = new TimerTask()
		{
			public void run() 
			{
				nextExecuteTime += 2 * 60 * 1000;
				System.out.println("Timer task execute " + ++times + " at " + new Date() + 
						",expected executing at " +  new Date(nextExecuteTime));
			}
		};
		
		ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
		service.scheduleAtFixedRate(task, 0, 2, TimeUnit.MINUTES);
	}

}

  上述两段代码可在运行时,分别先后将时间向后修改,观察控制台输出效果,再向前修改并观察效果。

      Spring的Schedule支持多种定时任务实现,具体可参考http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html#threadPoolTaskExecutor

      使用上述Timer时,配置如下(已过时,建议不要再使用)

<context:component-scan base-package="com.bryan.schedule"  use-default-filters="false">
    <context:include-filter type="regex" expression="com.bryan.schedule.SpringTimer.*"/>
 </context:component-scan>
 
 <bean id="testTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
         <property name="timerTask">
            <ref bean ="timer"/>
         </property>
         <property name="period">
            <value>120000</value>
         </property>
         <property name="delay">
            <value>0</value>
         </property>
    </bean>
 <bean class="org.springframework.scheduling.timer.TimerFactoryBean">
        <property name="scheduledTimerTasks">
            <list>
                <ref local="testTask" />
            </list>
        </property>
    </bean>

  

      使用ScheduledExecutorService时,配置如下

	<bean id="testTask" class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
         <property name="runnable">
            <ref bean ="timer"/>
         </property>
         <property name="period">
            <value>120000</value>
         </property>
         <property name="delay">
            <value>0</value>
         </property>
         <property name="fixedRate">
             <value>true</value>
         </property>
    </bean>
	<bean class="org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean">
        <property name="scheduledExecutorTasks">
            <list>
                <ref local="testTask" />
            </list>
        </property>
    </bean>

  

 

抱歉!评论已关闭.