Timer 和 TimerTask 定时任务
TimerTask 类
public abstract class TimerTask implements Runnable {
/**
* 控制访问timertask内部的锁
*/
final Object lock = new Object();
/**
* 初始状态为0,就是还没有被计划执行
*/
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() {
}
/**
* 会被子类实现,run的内容就是任务的内容
*/
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);
}
}
}
TaskQueue类源码
class TaskQueue {
/**
* 优先级任务对列,队列初始化的长度为128,这个队列是一个最小堆
* 最小堆就是父节点总是小于等于子节点,这里的大小是任务执行的时刻,任务执行的时刻
* 最小的,放在根节点,就是按照先后顺序
*/
private TimerTask[] queue = new TimerTask[128];
/**
* 优先级对列中的任务数
*/
private int size = 0;
/**
* 返回size的值
*/
int size() {
return size;
}
/**
* 向对列添加一个任务
*/
void add(TimerTask task) {
// 如果队列中任务数要满的时候,就扩展队列的长度为2倍
if (size + 1 == queue.length)
queue = Arrays.copyOf(queue, 2*queue.length);
queue[++size] = task; //将任务添加到队列中
fixUp(size); //在队列末尾插入一个任务后,要重新调整最小堆,以保证最小堆的大小顺序
}
/**
* 返回最小堆中的根节点,最小的执行时间的任务
*/
TimerTask getMin() {
return queue[1];
}
/**
* 根据下标i,返回任务
*/
TimerTask get(int i) {
return queue[i];
}
/**
* 删除最小的任务(根节点),然后将队列末尾的那个值放在根节点处,再调整堆的顺序
*/
void removeMin() {
queue[1] = queue[size];
queue[size--] = null;
fixDown(1);
}
/**
* 直接删除第i个节点,然后将队列末尾的那个节点占据i节点位置,不调整堆的顺序
*/
void quickRemove(int i) {
assert i <= size;
queue[i] = queue[size];
queue[size--] = null;
}
/**
* 设置根节点的执行时间,然后重新调整堆的顺序
*/
void rescheduleMin(long newTime) {
queue[1].nextExecutionTime = newTime;
fixDown(1);
}
/**
* 判断任务数是否为0
*/
boolean isEmpty() {
return size==0;
}
/**
* 将这个队列清空
*/
void clear() {
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;
}
}
/**
* 从k节点从上向下调整堆顺序
*/
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);
}
}
最大堆 ,父节点的值总是大于等于子节点的值。
一个节点的下标,比如 7>>1 就跑到了父节点,6也是。
一个节点的下标,比如 1<<1,就跑到了左子节点2,然后2+1,就跑到了右子节点3。
TimerThread类源码
class TimerThread extends Thread {
/**
* true代表队列中已经没有任务了,false代表Timer对象的引用已经无效了
*/
boolean newTasksMayBeScheduled = true;
/**
* 任务队列,最小堆
*/
private TaskQueue queue;
TimerThread(TaskQueue queue) { //构造方法
this.queue = queue;
}
public void run() {
try {
mainLoop();
} finally {
// Someone killed this Thread, behave as if Timer cancelled
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); // Eliminate obsolete references
}
}
}
/**
* The main timer loop. (See class comment.)
*/
private void mainLoop() {
while (true) {
try {
TimerTask task;
boolean taskFired;
synchronized(queue) {
// Wait for queue to become non-empty
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) { // Non-repeating, remove
queue.removeMin();
task.state = TimerTask.EXECUTED;
} else { // Repeating task, reschedule
queue.rescheduleMin(
task.period<0 ? currentTime - task.period
: executionTime + task.period);
}
}
}
if (!taskFired) // Task hasn't yet fired; wait
queue.wait(executionTime - currentTime);
}
if (taskFired) // Task fired; run it, holding no locks
task.run();
} catch(InterruptedException e) {
}
}
}
}