Timer总结
Timer是jdk自带的定时器,可以实现单机基本的定时任务, 从指定时间开始,每隔一段时间固定执行等等;它主要具有以下特性
1.单线程同步处理所有任务(TimerTask), 所以任务真正执行的时间点可能和预定的有延迟(因为有可能被前面的任务给耽误了)
2.只要有任务在执行时抛出了异常(InterruptedException除外的所有异常),整个Timer被停止,所有任务也被停止;
3.任务队列基于优先队列,二叉堆来实现的,以保证任务总体上的有序执行
Timer两个重要的成员变量
TimerThread实例对象,实现主循环,选择一个最近要执行的任务进行执行
TaskQueue实例对象,实现了任务队列, 内部实现是优先队列的数据结构
private final TaskQueuequeue =new TaskQueue();
private final TimerThreadthread =new TimerThread(queue);
Timer初始化
通过构造函数在实例化的时候即启动内部线程类TimerThread
public Timer(String name, boolean isDaemon) {
thread.setName(name);
thread.setDaemon(isDaemon);
thread.start();
TimerThread线程启动后调用 mainLoop 一直尝试从优先队列里获取任务(最先待执行的任务)
当队列为空时主循环就一直wait();
当队列不为空时,取队头的任务(即堆顶)并比较任务的执行时间nextExecutionTime与当前时间currentTime,如果时间未到则需要阻塞等待 queue.wait(executionTime - currentTime);
class TimerThreadextends Thread {
private TaskQueuequeue;
TimerThread(TaskQueue queue) {
this.queue = queue;
}
public void run() {
try {
mainLoop();
}finally {
。。。
}
}
/**
* The main timer loop. (See class comment.)
*/
private void mainLoop() {
while (true) {
try {
....主循环,一直尝试获取任务...
if (!taskFired) queue.wait(executionTime - currentTime);
.......
if (taskFired) task.run();
}catch(InterruptedException e) {
}
}
Timer添加任务
添加的任务都是TimerTask的子类,类似schedule(TimerTask xxx), 即往TaskQueue队列里添加任务, 当发现队列里面刚刚没有数据时则进行notify, 以便唤醒TimerThread继续执行; 见加粗代码部分
添加任务操作最终都会调用 private void sched(TimerTask task, long time, long period)
private void sched(TimerTask task, long time, long period) {
if (time <0)
throw new IllegalArgumentException("Illegal execution time.");
// Constrain value of period sufficiently to prevent numeric
// overflow while still being effectively infinitely large.
if (Math.abs(period) > (Long.MAX_VALUE >>1))
period >>=1;
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}