timer与ScheduledExecutorService

来源:互联网 发布:java开发养成游戏视频 编辑:程序博客网 时间:2024/05/19 17:05

Timer和ScheduledExecutorService都可以用来做定时任务,有管理任务延迟执行("如1000ms后执行任务")以及周期性执行("如每500ms执行一次该任务")。但至从JDK1.5之后,建议采用ScheduledExecutorService。

原因如下:

1、Timer对调度的支持是基于绝对时间,而不是相对时间的,由此任务对系统时钟的改变是敏感的;但ScheduledThreadExecutor只支持相对时间。

2、如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以 TimerTask抛出的未检查的异常会终止timer线程。此时,已经被安排但尚未执行的TimerTask永远不会再执行了,新的任务也不能被调度了。

下面例子介绍了ScheduledExecutorService与Calendar的一个应用,用来解决一些复杂的时间问题,比如每个星期二的16点38分执行!当然如果采用spring的任务调度的话会简单得多

复制代码
package com.qinsoft.test;import java.util.Calendar;import java.util.Date;import java.util.TimerTask;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ScheduledExceutorTest extends TimerTask {    private String jobName = "";    public ScheduledExceutorTest(String jobName) {        super();        this.jobName = jobName;    }    @Override    public void run() {        System.out.println("Date = "+new Date()+", execute " + jobName);    }    /**     * 计算从当前时间currentDate开始,满足条件dayOfWeek, hourOfDay,      * minuteOfHour, secondOfMinite的最近时间     * @return     */    public Calendar getEarliestDate(Calendar currentDate, int dayOfWeek,int hourOfDay, int minuteOfHour, int secondOfMinite) {        //计算当前时间的WEEK_OF_YEAR,DAY_OF_WEEK, HOUR_OF_DAY, MINUTE,SECOND等各个字段值        int currentWeekOfYear = currentDate.get(Calendar.WEEK_OF_YEAR);        int currentDayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK);        int currentHour = currentDate.get(Calendar.HOUR_OF_DAY);        int currentMinute = currentDate.get(Calendar.MINUTE);        int currentSecond = currentDate.get(Calendar.SECOND);        //如果输入条件中的dayOfWeek小于当前日期的dayOfWeek,则WEEK_OF_YEAR需要推迟一周        boolean weekLater = false;        if (dayOfWeek < currentDayOfWeek) {            weekLater = true;        } else if (dayOfWeek == currentDayOfWeek) {            //当输入条件与当前日期的dayOfWeek相等时,如果输入条件中的            //hourOfDay小于当前日期的            //currentHour,则WEEK_OF_YEAR需要推迟一周               if (hourOfDay < currentHour) {                weekLater = true;            } else if (hourOfDay == currentHour) {                 //当输入条件与当前日期的dayOfWeek, hourOfDay相等时,                 //如果输入条件中的minuteOfHour小于当前日期的                //currentMinute,则WEEK_OF_YEAR需要推迟一周                if (minuteOfHour < currentMinute) {                    weekLater = true;                } else if (minuteOfHour == currentSecond) {                     //当输入条件与当前日期的dayOfWeek, hourOfDay,                      //minuteOfHour相等时,如果输入条件中的                    //secondOfMinite小于当前日期的currentSecond,                    //则WEEK_OF_YEAR需要推迟一周                    if (secondOfMinite < currentSecond) {                        weekLater = true;                    }                }            }        }        if (weekLater) {            //设置当前日期中的WEEK_OF_YEAR为当前周推迟一周            currentDate.set(Calendar.WEEK_OF_YEAR, currentWeekOfYear + 1);        }        // 设置当前日期中的DAY_OF_WEEK,HOUR_OF_DAY,MINUTE,SECOND为输入条件中的值。        currentDate.set(Calendar.DAY_OF_WEEK, dayOfWeek);        currentDate.set(Calendar.HOUR_OF_DAY, hourOfDay);        currentDate.set(Calendar.MINUTE, minuteOfHour);        currentDate.set(Calendar.SECOND, secondOfMinite);        return currentDate;    }    public static void main(String[] args) throws Exception {        ScheduledExceutorTest2 test = new ScheduledExceutorTest2("job1");        //获取当前时间        Calendar currentDate = Calendar.getInstance();        long currentDateLong = currentDate.getTime().getTime();        System.out.println("Current Date = " + currentDate.getTime().toString());        //计算满足条件的最近一次执行时间        Calendar earliestDate = test.getEarliestDate(currentDate, 3, 16, 38, 10);        long earliestDateLong = earliestDate.getTime().getTime();        System.out.println("Earliest Date = "+ earliestDate.getTime().toString());        //计算从当前时间到最近一次执行时间的时间间隔        long delay = earliestDateLong - currentDateLong;        //计算执行周期为一星期        long period = 7 * 24 * 60 * 60 * 1000;        ScheduledExecutorService service = Executors.newScheduledThreadPool(10);        //从现在开始delay毫秒之后,每隔一星期执行一次job1        service.scheduleAtFixedRate(test, delay, period, TimeUnit.MILLISECONDS);    }} 
复制代码