java定时操作之Timer和TimerTas(一)

2014-11-24 01:45:17 · 作者: · 浏览: 0

Timer类是一种线程设施,可以用来实现某一个时间或某一段时间后安排某一个任务执行一次或定期重复执行。该功能和TimerTask配合使用。TimerTask类用于实现由Timer安排的一次或重复执行的某个任务。每一个Timer对象对应的是一个线程,因此计时器所执行的任务应该迅速完成,否则会延迟后续的任务执行。

一、 深入JDK源代码TimerTask类,发现这个类是个抽象类比较简单,有四个常量表示定时器任务的状态,还有一个Object类型lock对象,相当一把锁,控制线程对定时器任务状态的同步访问。

nextExecutionTime 这个成员变量用到记录该任务下次执行时间, 其格式和System.currentTimeMillis()一致. 这个值是作为任务队列中任务排序的依据. 任务调试者执行每个任务前会对这个值作处理,重新计算下一次任务执行时间,并为这个变量赋值.

period 用来描述任务的执行方式: 0表示不重复执行的任务. 正数表示固定速率执行的任务. 负数表示固定延迟执行的任务. (固定速率: 不考虑该任务上一次执行情况,始终从开始时间算起的每period执行下一次. 固定延迟: 考虑该任务一次执行情况,在上一次执行后period执行下一次).

代码如下:

Java代码

public abstract class TimerTask implements Runnable {

//这个对象是用来控制访问TimerTask内部构件。锁机制

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);

}

}

}

public abstract class TimerTask implements Runnable {

//这个对象是用来控制访问TimerTask内部构件。锁机制

final Object lock = new Object();

//定时器任务的状态

int state = VIRGIN;

//定时器任务默认的状态,表示还没有被安排

static final int VIRGIN = 0;

//表示定时器任务被安排了

static final int SCHEDULED = 1; dedecms.com

//表示定时器任务执行

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);

}

}

}

二、深入JDK源代码之Timer类,Timer中最主要由三个部分组成: 任务TimerTask 、 任务队列: TaskQueue queue 和 任务调试者:TimerThread thread

1.任务队列TaskQueue,它是Timer的一个内部类。

事实上任务队列是一个数组, 采用平衡二叉堆来实现他的优先级调度, 并且是一个小顶堆. 需要注意的是, 这个堆中queue[n] 的孩子是queue[2*n] 和queue[2*n+1].

任务队列的优先级按照TimerTask类的成员变量nextExecutionTime值来排序(注意, 这里的任务指的是那些交由定时器来执行的, 继承TimerTask的对象).

在任务队列中, nextExecutionTime最小就是所有任务中最早要被调度来执行的, 所以被安排在queue[1] (假设任务队列非空).

对于堆中任意一个节点n, 和他的任意子孙节点d,一定遵循: n.nextExecutionTime <= d.nextExecutionTime.

Java代码

// 任务队列

class TaskQueue {

// 计时器任务数组,默认大小为128

private TimerTask[] queue = new TimerTask[128];

private int size = 0;

int size() {

return size;

}

// 加入队列

void add(TimerTask task) {

// Grow backing store if necessary

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; // Dr