Timer,定时器,一个功能强大的类。
线程通过它来安排以后需要在线程中执行的任务。该任务可以执行一次,也可以周期重复执行。
Timer类中 包含了一个线程TimerThread、一个任务数组类TaskQueue。工作原理是 TimerThread不停的循环执行TaskQueue中的任务(TimerTask、定时任务)。
重要的成员变量:
public class Timer {
/** 任务数组 */
private final TaskQueue queue = new TaskQueue();
/** 计时器线程(封装了任务队列) */
private final TimerThread thread = new TimerThread(queue);
………
}
TimerThread
我们先来分析一下TimerThread,它的主要工作就是循环执行TaskQueue类中数组的当前需要执行的TimerTask。
该类内容不多,直接上源码。
class TimerThread extends Thread { /** 是否有新的任务已经被调度,当没有执行 */ boolean newTasksMayBeScheduled = true; /** 任务队列 */ private TaskQueue queue; TimerThread(TaskQueue queue) { this.queue = queue; } /** 定时线程的run()*/ public void run() { try { mainLoop(); } finally { // Someone killed this Thread, behave as if Timer cancelled synchronized(queue) { newTasksMayBeScheduled = false; queue.clear(); // Eliminate obsolete references } } } /** 定时器主循环*/ private void mainLoop() { while (true) { try { TimerTask task; boolean taskFired; synchronized(queue) { /** 等待任务数组非空 */ while (queue.isEmpty() && newTasksMayBeScheduled) queue.wait(); if (queue.isEmpty()) break; // Queue is empty and will forever remain; die // Queue nonempty; look at first evt and do the right thing long currentTime, executionTime; task = queue.getMin(); /** 得到第一个任务*/ synchronized(task.lock) { /** 得到锁 */ if (task.state == TimerTask.CANCELLED) { queue.removeMin(); continue; // No action required, poll queue again } currentTime = System.currentTimeMillis(); executionTime = task.nextExecutionTime; if (taskFired = (executionTime<=currentTime)) { /** 比较任务是否满足执行条件:时间是否到达。时间到了执行*/ if (task.period == 0) { /** 是否是周期任务,不是周期任务则执行、并删除*/ queue.removeMin(); task.state = TimerTask.EXECUTED; } else { /** 是周期函数,执行、并重新计算下一次的执行时间*/ queue.rescheduleMin( task.period<0 ? currentTime - task.period : executionTime + task.period); } } } if (!taskFired) /** 任务的规定时间没到,则更新需要等待的时间,以备下一次执行*/ queue.wait(executionTime - currentTime); } if (taskFired) task.run(); } catch(InterruptedException e) { } } } }
上面代码我们可以看到,TimerThread线程的run()主要工作是执行TaskQueue queue.getMin()返回的任务task,
1、task的执行时间达到,那么我们执行该任务,如果是周期任务,更新下一次的执行时间,如果是一次性任务,执行之后从任务数组中删除。
2、task执行时间未达到,更新数组queue中全部任务需要等待的时间。
那么TaskQueue又是怎么工作的呢?
TaskQueue
上文已经说到,TaskQueue是保存了一个任务数组的类。
源码我们可以看到,主要成员变量为 TimerTask[] queue 其实就是一个任务数组。
我们上文中queue.getMin():返回编号为1的任务,也就是距离当前执行时间最短的那个任务。编号为0不用。
该数组排序是根据 任务的等待时间 安装堆排序的方法进行放置。
class TaskQueue { /** 堆化排序*/ private TimerTask[] queue = new TimerTask[128]; private int size = 0; /** 返回任务的数量*/ int size() { return size; } /** 增加task到任务队列中 */ void add(TimerTask task) { // 如果有必要扩展队列大小 if (size + 1 == queue.length) queue = Arrays.copyOf(queue, 2*queue.length); queue[++size] = task; fixUp(size); } /** 得到第一个任务*/ TimerTask getMin() { return queue[1]; } /** 得到指定任务*/ TimerTask get(int i) { return queue[i]; } /** 删除第一个任务*/ void removeMin() { queue[1] = queue[size]; queue[size--] = null; // Drop extra reference to prevent memory leak fixDown(1); } /** 删除指定任务 */ void quickRemove(int i) { assert i <= size; queue[i] = queue[size]; queue[size--] = null; // Drop extra ref to prevent memory leak } /** 重写调度第一个任务 */ void rescheduleMin(long newTime) { queue[1].nextExecutionTime = newTime; fixDown(1); } /** 任务数组是否为空*/ boolean isEmpty() { return size==0; } /** 清空任务数组 */ void clear() { // Null out task references to prevent memory leak for (int i=1; i<=size; i++) queue[i] = null; size = 0; } /** 对第k个任务进行重新排序(堆排序),(默认其他任务顺序正常)*/ private void fixUp(int k) { while (k > 1) { int j = k >> 1; if (queue[j].nextExecutionTime <= queue[k].nextExecutionTime) break; TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp; k = j; } } /** 用于重排一个个任务*/ private void fixDown(int k) { int j; while ((j = k << 1) <= size && j > 0) { if (j < size && queue[j].nextExecutionTime > queue[j+1].nextExecutionTime) j++; // j indexes smallest kid if (queue[k].nextExecutionTime <= queue[j].nextExecutionTime) break; TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp; k = j; } } /** 堆化排序 */ void heapify() { for (int i = size/2; i >= 1; i--) fixDown(i); } }
TimerTask
另外还有一个重要的类就是 :TimerTask定时任务。
TimerTask是我们直接需要执行任务的具体内容。其中的run(),就是我们想要在某个时间做的具体事务。
/********************************************************* * TimerTask 安排为一次执行或重复执行的任务 * 实际上是一个实现了Runnable接口的类。具体执行任务为run() * ********************************************************/ public abstract class TimerTask implements Runnable { /** 锁 */ final Object lock = new Object(); /** 任务的当前状态 */ int state = VIRGIN; /** 任务还没有被调度安排 */ static final int VIRGIN = 0; /** 表示已经被调度安排,没有被执行*/ static final int SCHEDULED = 1; /** 已经被执行或者正在执行,没有被取消 */ static final int EXECUTED = 2; /** 已经被取消 */ static final int CANCELLED = 3; /** 下一次的执行时间*/ long nextExecutionTime; /** 任务周期*/ long period = 0; /** 构造器*/ protected TimerTask() { } /** 按时执行的操作*/ public abstract void run(); /** 取消计时器任务 */ public boolean cancel() { synchronized(lock) { boolean result = (state == SCHEDULED); state = CANCELLED; return result; } } /** 返回此任务最近实际执行的安排执行时间 */ public long scheduledExecutionTime() { synchronized(lock) { return (period < 0 ? nextExecutionTime + period : nextExecutionTime - period); } } }