源码均以JDK1.8作为参考
JDK1.3中为定时任务提供了一种简单实现,java.util.Timer类调度java.util.TimerTask任务。
TimerTask:
TimerTask为Timer定时任务的执行提供了最小执行单元,TimerTask继承自Runnable接口,TimerTask本身是一个抽象类,给继承自Runnable接
口的TimerTask更加详细的描述。
TimerTask任务有四个状态:
VIRGIN = 0:表明此任务还未被调度
SCHEDULED = 1:表明此任务时一个调度任务,但是还未执行
EXECUTED = 2:表明此任务已经处在执行状态
CANCELLED = 3:表明此任务已经被取消
其中TimerTask中还有几个比较重要的内部参数,简单介绍一下:
Object lock: 对象锁,TimerTask在执行具体的操作时,提供了synchronized同步原语操作,例如当run()执行时,应该禁止
cancel()的执行,此时可以使用synchronized(lock)对当前任务进行同步控制。
long nextExecutionTime:在TimerTask初始初期,计算的任务执行时间点
long period :对于定时任务,给定的间隔时间
在JDK的TimerTask实现中,TimerTask提供了cancel()和scheduledExecutionTime()的实现,而具体任务执行内容的run()方法,委托给了
子类具体实现。
Timer:
Timer类可以看作是TimerTask任务的管理和调度类,在Timer类文件中还有两个非public的类实现:TaskQueue和TimerThread,接下来让我们
一一看看Timer的具体实现:
TaskQueue:
TaskQueue为Timer中TimerTask管理提供了一个队列,可以向这个队列中增加和移除任务,以达到管理TimerTask任务的目的。
TaskQueue实例化时,会默认初始一个长度为128的TimerTask数组,来存储TimerTask,如下:
TimerTask[] queue = new TimerTask[128]
当想TaskQueue中add任务时,若内部数组已满,则将数组长度扩展为当前的2倍。
TaskQueue只是一个类队列,不具有队列的通用特性,TaskQueue提供了维护内部数据的一些公开方法,以便Timer对其进行管理。
TaskThread:
TaskThread的Timer线程类,它的主要作用是在Timer建立后,监控Timer的状态,主要监控Timer的TaskQueue中是否有任务在排队,如果
有,则根据具体的TimerTask实现类进行TimerTask任务的执行。
其灵魂内容就是mainLoop(), 源码如下:
private void mainLoop() {
while (true) {
// .. 具体参见源码
}
}
mainLoop自线程start后,会一直监视Timer中TimerQueue的内容和状态,并根据数据对不同的情况作出不一样的反应。
Timer:
上文提到的三个类,都是任务调度实现的组成部分,而这些部分最终是由Timer类串联起来的,Timer类在其中充当了管理的角色。
首先我们来看:
1.内部结构:
Timer中维护了两个私有变量,分别是TaskQueue和TaskThread的实例,如下:
private final TaskQueue queue = new TaskQueue();
private final TimerThread thread = new TimerThread(queue);
2.初始化:
Timer提供了四个重载的构造方法,如下:
public Timer():
public Timer(boolean isDaemon)
public Timer(String name)
public Timer(String name, boolean isDaemon)
name表示TaskThread的名称,isDaemon表示将TaskThread设置为用户线程或者守护线程。
当调用构造函数初始化时,会TaskThread的start()方法,使线程进入运行状态,此时,TaskThread会监控Timer中TaskQueue的内容和状
态,作出反应。
3.schedule与scheduleAtFixedRate:
Timer对外公开的方法中:
public void schedule(TimerTask task, long delay)
public void schedule(TimerTask task, Date time)
public void schedule(TimerTask task, long delay, long period)
public void schedule(TimerTask task, Date firstTime, long period)
Timer中还有另一类执行任务方法:
public void scheduleAtFixedRate(TimerTask task, long delay, long period)
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
区别:
schedule与scheduleAtFixRate的区别在任务执行起始的时间基准点不一样。
schedule方法:下一次执行时间相对于 上一次 实际执行完成的时间点 ,因此执行时间会不断延后
scheduleAtFixedRate方法:下一次执行时间相对于上一次开始的 时间点 ,因此执行时间不会延后,存在并发性
示例如下:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, startDate, 5 * 1000);