Java Timer 源码深入分析

源码均以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);



   

你可能感兴趣的:(JDK,源码分析)