当前位置:首页 > 开发 > 编程语言 > Java > 正文

Java定时任务调度:用ExecutorService取代Timer

发表于: 2013-11-25   作者:bylijinnan   来源:转载   浏览:
摘要: 《Java并发编程实战》一书提到的用ExecutorService取代Java Timer有几个理由,我认为其中最重要的理由是: 如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以 TimerTask抛出的未检查的异常会终止timer线程。这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。此时,已经被
《Java并发编程实战》一书提到的用ExecutorService取代Java Timer有几个理由,我认为其中最重要的理由是:
如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以 TimerTask抛出的未检查的异常会终止timer线程。这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。此时,已经被安排但尚未执行的TimerTask永远不会再执行了,新的任务也不能被调度了。

stackoverflow上也有关于此问题的讨论:
http://stackoverflow.com/questions/409932/java-timer-vs-executorservice

Timer的问题:
package com.ljn.timer;

import java.util.Date;
import java.util.Timer;

/**
 * @author lijinnan
 * @date:2013-11-25 下午3:27:43  
 */
public class TimerException {

    public static void main(String[] args) {
        System.out.println("start:" + new Date());
        Timer timer = new Timer();
        int delay = 1000;
        int period = 2000;
        timer.schedule(new OKTask(), delay * 2, period);    //"OKTask" does not get chance to execute
        timer.schedule(new ErrorTask(), delay, period);  //exception in "ErrorTask" will terminate the Timer
    }
    
    /*输出:
start:Mon Nov 25 17:49:53 CST 2013
ErrorTask is executing...
error:Mon Nov 25 17:49:55 CST 2013
Exception in thread "Timer-0" java.lang.RuntimeException: something wrong
    at com.ljn.timer.ErrorTask.run(ErrorTask.java:14)
     */

 }



用ExecutorService则正常:
package com.ljn.timer;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author lijinnan
 * @date:2013-11-25 下午3:35:39  
 */
public class ScheduledExecutorServiceTest {

    public static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);  

    public static void main(String[] args){
        System.out.println("start:" + new Date());
        ErrorTask errorTask = new ErrorTask();
        OKTask okTask = new OKTask();
        int delay = 1000;
        int period = 2000;
        scheduledExecutorService.scheduleAtFixedRate(errorTask, delay, period, TimeUnit.MILLISECONDS);   //"ErrorTask" throws Exception and then stopes.
        scheduledExecutorService.scheduleAtFixedRate(okTask, delay * 2, period, TimeUnit.MILLISECONDS);     //"OKTask" is executed periodically, not affected by "ErrorTask"
        
        //scheduledExecutorService.shutdown();
    }

    /*
start:Mon Nov 25 17:54:22 CST 2013
ErrorTask is executing...
error occurs:Mon Nov 25 17:54:24 CST 2013
OKTask is executed:Mon Nov 25 17:54:24 CST 2013
OKTask is executed:Mon Nov 25 17:54:26 CST 2013
OKTask is executed:Mon Nov 25 17:54:28 CST 2013
......
     */

}



另外开发中常常会让任务在每天的指定时间点运行,示例如下:
package com.ljn.timer;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author lijinnan
 * @date:2013-11-25 下午5:18:55  
 */
public class FixedDatetimeTaskTest {

    public static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);  

    public static void main(String[] args) throws Exception {
        System.out.println("start:" + new Date());
        
        //每天的02:30:00执行任务
        long delay = Helper.calcDelay(2, 30, 0);
        long period = Helper.ONE_DAY;
        scheduledExecutorService.scheduleAtFixedRate(new OKTask(), delay, period, TimeUnit.MILLISECONDS); 
    }

}



文章中用到的其他类:
package com.ljn.timer;

import java.util.Date;
import java.util.TimerTask;

public class ErrorTask extends TimerTask {

     @Override
     public void run() {
         try {
             System.out.println("ErrorTask is executing...");
             Thread.sleep(1000);
             System.out.println("error occurs:" + new Date());
             throw new RuntimeException("something wrong");
         } catch (InterruptedException e) {
         }
     }
     
 }


package com.ljn.timer;

import java.util.Date;
import java.util.TimerTask;

 
public  class OKTask extends TimerTask {
     
     @Override
     public void run() {
         System.out.println("OKTask is executed:" + new Date());
     }
}


package com.ljn.timer;

import org.joda.time.DateTime;

/**
 * @author lijinnan
 * @date:2013-11-25 下午5:17:40  
 */
public class Helper {

    private Helper() {}
    
    public static final long ONE_DAY = 60 * 60 * 24;
    
    public static long calcDelay(int hour, int minute, int second) {
        if (!(0 <= hour && hour <=23 && 0 <= minute && minute <=59 && 0 <=second && second <= 59)) {
            throw new IllegalArgumentException();
        }
        return calcDelay(fixed(hour, minute, second));
    }
    
    private static long calcDelay(DateTime targetDatetimeOfToday) {
        long delay = 0;
        DateTime now = new DateTime();
        
        //时间点已过,只好延时到明天的这个时间点再执行
        if (now.isAfter(targetDatetimeOfToday)) {
            delay = now.plusDays(1).getMillis() - now.getMillis();
            
        //时间点未到
        } else {
            delay = targetDatetimeOfToday.getMillis() - now.getMillis();
        }
        
        return delay;
    }
    
    /**
     * 返回这样一个DateTime对象:
     * 1.日期为今天
     * 2.时分秒为参数指定的值
     * @param hour 0-23
     * @param minute 0-59
     * @param second 0-59
     * @return
     */
    private static DateTime fixed(int hour, int minute, int second) {
        
        return new DateTime()
                    .withHourOfDay(hour).withMinuteOfHour(minute).withSecondOfMinute(second);
    }

}

Java定时任务调度:用ExecutorService取代Timer

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
故事起因 因业务需要,写了一个定时任务Timer,任务将在每天的凌晨2点执行,代码顺利码完,一切就绪
定时调度:每当一到时间,程序会自动执行,称为定时调度。 如果要使用定时调度,则必须保证程序始终
原文:java定时任务类Timer和TimerTask用法详解 代码下载地址:http://www.zuidaima.com/share/1550
目前定时任务调度系统quartz比较出名,quartz也有集群方案,但把所有任务集中一起就构成了分布式任
一. 业务需求: 实际工作中我们通常会遇到这样的需求: 使用Ajax技术每隔几秒从缓存或数据库中读取一
上篇博文《任务调度(三)——Timer的替代品ScheduledExecutorService简介》已经对ScheduledExecutorS
说到任务调度,大家可能会想到Quartz框架,但是jdk自带的简单任务调度工具类,反而了解的人并不是很
说到任务调度,大家可能会想到Quartz框架,但是jdk自带的简单任务调度工具类,反而了解的人并不是很
先前的两篇博文《任务调度(一)——jdk自带的Timer》和《任务调度(二)——jdk自带的Timer 动态修改任
定时调度:每当一段时间,程序会自动执行,称为定时调度。 如果要使用定时调度,则必须保证程序始终
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号