在java中,通过使用Timer类和TimderTask类来完成实现定时任务的执行
先看一个很简单的例子:
范例1:
import java.util.*; import java.text.*; public class TimerDemo{ public static void main (String [] args) throws Exception { Timer timer = new Timer(); System.out.println("start at :" + new Date()); timer.schedule(new TaskDemo(),5000); } } class TaskDemo extends TimerTask{ public void run(){ System.out.println("current time is :" + new Date()); } }
输出内容为:
start at :Thu Apr 18 16:25:08 CST 2013
current time is :Thu Apr 18 16:25:13 CST 2013
范例1在5秒延迟后执行一次调度任务,这个很简单
范例2:
timer.schedule(new TaskDemo(),5000,2000);
输出结果为:
start at :Thu Apr 18 16:28:18 CST 2013
current time is :Thu Apr 18 16:28:23 CST 2013
current time is :Thu Apr 18 16:28:25 CST 2013
current time is :Thu Apr 18 16:28:27 CST 2013
范例2是在5秒延迟后每隔2秒钟执行一次任务
void |
schedule(TimerTask task, Date time) |
void |
schedule(TimerTask task, Date firstTime, long period) |
上面这两个是从指定的日期时间开始执行一次,或者重复执行
当第一次执行的时间fristTime如果还没到也就将来的时间的话,那么程序将会阻塞直到当前时间为指定的firstTime。
那么如果指定的时间已经过去了呢?此时程序会立即开始执行一次,或按照时间间隔多次执行,见范例3:
范例3:
Date targetStartDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse("2013-04-18 16:33:00"); timer.schedule(new TaskDemo(),targetStartDate,2000);
部分输出:
start at :Thu Apr 18 16:34:53 CST 2013
current time is :Thu Apr 18 16:34:53 CST 2013
current time is :Thu Apr 18 16:34:55 CST 2013
current time is :Thu Apr 18 16:34:57 CST 2013
current time is :Thu Apr 18 16:34:59 CST 2013
从结果可以看出,程序执行的时间是53秒,调度器马上执行一遍,然后按照当前实际的时间开始计算,在2秒的间隔后重复执行,已经过去的时间忽略处理。
另一种方式:必须固定频率来执行任务调度,这就需要下面两个方法:
void |
scheduleAtFixedRate(TimerTask task, Date firstTime, long period) |
void |
scheduleAtFixedRate(TimerTask task, long delay, long period) |
范例4
Date targetStartDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse("2013-04-18 16:41:00"); timer.scheduleAtFixedRate(new TaskDemo(),targetStartDate,2000);
部分输出:
start at :Thu Apr 18 16:41:08 CST 2013
current time is :Thu Apr 18 16:41:08 CST 2013
current time is :Thu Apr 18 16:41:08 CST 2013
current time is :Thu Apr 18 16:41:08 CST 2013
current time is :Thu Apr 18 16:41:08 CST 2013
current time is :Thu Apr 18 16:41:08 CST 2013
current time is :Thu Apr 18 16:41:10 CST 2013
current time is :Thu Apr 18 16:41:12 CST 2013
current time is :Thu Apr 18 16:41:14 CST 2013
current time is :Thu Apr 18 16:41:16 CST 2013
从结果来看:程序在08秒开始执行,指定开始时间是00秒,如果按照schedule方法来设置调度任务的话就会立即执行,然后再去重复调度
但scheduleAtFixedRate来设置的话,因为是固定频率,所以会把已经“经过的时间”内需要执行的次数全部执行一遍,然后再按照当前实际的时间去调度。
当重复调度的过程中如果其中一个因为特殊原因被延迟了导致不能按照既定调度时间和频率执行是,schedule和scheduleAtFixedRate是如何处理的
范例5
import java.util.*; import java.text.*; public class TimerDemo{ public static void main (String [] args) throws Exception { Timer timer = new Timer(); System.out.println("start at :" + new Date()); timer.schedule(new TaskDemo(),1000,2000); } } class TaskDemo extends TimerTask{ public static int count = 0 ; public void run() { if(count++ == 3){ try{ Thread.sleep(10000); }catch(Exception e){} } System.out.println("current time is :" + new Date()); } }
输出:
start at :Thu Apr 18 16:53:48 CST 2013
current time is :Thu Apr 18 16:53:49 CST 2013
current time is :Thu Apr 18 16:53:51 CST 2013
current time is :Thu Apr 18 16:53:53 CST 2013
current time is :Thu Apr 18 16:54:05 CST 2013
current time is :Thu Apr 18 16:54:05 CST 2013
current time is :Thu Apr 18 16:54:07 CST 2013
current time is :Thu Apr 18 16:54:09 CST 2013
current time is :Thu Apr 18 16:54:11 CST 2013
当其中一个任务时间被延场后,然后再次开始运行,调度时间是从当前实际时间开始计算,另外为什么会在这里多执行一次调度任务我还不是很明白,因为不论我设置的睡眠时间是2秒,5秒,10秒,都是多重复执行一次,知道的朋友能否解释一下,谢谢
范例6:
timer.scheduleAtFixedRate(new TaskDemo(),1000,2000);
输出:
start at :Thu Apr 18 16:55:16 CST 2013
current time is :Thu Apr 18 16:55:17 CST 2013
current time is :Thu Apr 18 16:55:19 CST 2013
current time is :Thu Apr 18 16:55:21 CST 2013
current time is :Thu Apr 18 16:55:33 CST 2013
current time is :Thu Apr 18 16:55:33 CST 2013
current time is :Thu Apr 18 16:55:33 CST 2013
current time is :Thu Apr 18 16:55:33 CST 2013
current time is :Thu Apr 18 16:55:33 CST 2013
current time is :Thu Apr 18 16:55:33 CST 2013
current time is :Thu Apr 18 16:55:35 CST 2013
current time is :Thu Apr 18 16:55:37 CST 2013
可以看出,即使某一个任务被延迟,那么之后恢复调度的时候依然会将这个时间段内“漏掉”的任务执行一遍。
通过cancel方法可以终止Timer计时器。