0%

Timer的使用

Timer的使用

Timer是java中提供的定时任务调度,

在不使用第三方工具包的情况下可以使用Timer来实现定时器,不过Timer中提供的功能较少

Timer中的方法并不多

TimerTask

TimerTask实现Runnable接口

1
2
3
public abstract class TimerTask implements Runnable{

}

虽然TimerTask类实现了Runnable接口,但是该类并没有作为一个线程来使用,run方法只是作为一个普通的方法进行调用的

任务有四种状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 默认状态,还没有被调度
*/
static final int VIRGIN = 0;

/**
* 已经将任务塞进 TaskQueue 等待被执行
*/
static final int SCHEDULED = 1;

/**
* 表示任务已经执行完成,对于不可重复执行的任务来说,该任务正在被执行或者已经被执行
*/
static final int EXECUTED = 2;

/**
* 任务已经被取消
*/
static final int CANCELLED = 3;

schedule方法

schedule属于固定时延调度,会随着任务执行时间来顺延

1
2
3
4
5
6
7
public void schedule(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, -period);
}

可以看到,在传入sched方法时,period取反了

在执行任务时判断

1
2
3
4
5
6
7
8
9
10
11
12
13
// 下次执行时间小于当前时间
if (taskFired = (executionTime<=currentTime)) {
if (task.period == 0) { // Non-repeating, remove
queue.removeMin();
task.state = TimerTask.EXECUTED;
} else { // Repeating task, reschedule
queue.rescheduleMin(
// 如果period<0,则使用当前时间加上最初的那个间隔时间,所以时间会进行顺延
// 而如果period>0,则是执行时间加上间隔时间
task.period<0 ? currentTime - task.period
: executionTime + task.period);
}
}

scheduleAtFixedRate方法

scheduleAtFixedRate属于固定速率调度,

cancel方法

cancel用于取消任务

1
2
3
4
5
6
7
8
9
10
public void cancel() {
synchronized(queue) {
// Timer终止的标记
thread.newTasksMayBeScheduled = false;
// 清空队列
queue.clear();
// 唤醒等待中的线程,为了使TimerThread可以执行完成
queue.notify(); // In case queue was already empty.
}
}

purge方法

purge方法用于清空队列中CANCELLED状态的任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public int purge() {
int result = 0;

synchronized(queue) {
for (int i = queue.size(); i > 0; i--) {
if (queue.get(i).state == TimerTask.CANCELLED) {
queue.quickRemove(i);
result++;
}
}

if (result != 0)
queue.heapify();
}

return result;
}