Java中的Timer和Timer Task详解(一)

2014-11-24 11:41:59 · 作者: · 浏览: 23
Java Timer&TimerTask原理分析
如果你使用Java语言进行开发,对于定时执行任务这样的需求,自然而然会想到使用Timer和TimerTask完成任务,我最近就使用 Timer和TimerTask完成了一个定时执行的任务,实现得没有问题,但当在TimerTaks的run()方法中使用 Thread.sleep()方式时,可能会出现奇怪的现象,好像Timer失效了,网上查了一下,倒是有人遇到了相同的问题,但是并没有找到一篇解释为什么会出现这种情况,期待有某位达人能够分析清楚这个问题。
遇到了这样的问题,始终让我不爽,于是看了一下Timer的 源码,先将了解到的内容整理如下,接下来再看看Thread.sleep()的源码,看能否找到问题所在。
Java中,与定时任务执行相关的类很少,只有Timer、TimerTask、TimerThread、TaskQueue几个,其中每个类的职责大致如下:
Timer:一个Task的调度类,和TimerTask一样,暴露给最终用户使用的类,通过schedule方法安排Task的执行计划。该类通过TaskQueue和TimerThread类完成Task的调度。
TimerTask:实现Runnable接口,表明每一个任务均为一个独立的线程。通过run()方法提供用户定制自己任务。该类有一个比较重要的成员变量nextExecutionTime ,表示下一次执行该任务的时间。以后会看到,Timer机制就是靠这个值安排Task执行的。
TimerThread:继承于Thread,是真正执行Task的类。
TaskQueue:一个存储Task的数据结构,内部由一个最小堆实现,堆的每个成员为一个TimeTask,每个Task依靠其 nextExecutionTime值进行排序,也就是说,nextExecutionTime最小的任务在队列的最前端,从而能够现实最早执行。
要想使用Timer,用户只需要了解Timer和TimerTask,下面现已一个最基本的Timer和TimerTask使用案例入手,来看一下Timer内部的实现原理。
01
import java.util.Timer;
02
03
import java.util.TimerTask;
04
05
import org.junit.Test;
06
07
08
09
class TestTimerTask extends TimerTask {
10
11
@Override
12
13
public void run() {
14
15
System.out.println("TestTimerTask is running......");
16
17
}
18
19
}
20
21
public class TimerTaskTest {
22
23
@Test
24
25
public void testTimerTask() {
26
27
Timer timer = new Timer();
28
29
timer.schedule(new TestTimerTask(), 0, 10);
30
31
}
32
33
}
上面的代码是一个典型的Timer&TimerTask的应用,下面先来看一下new Timer()干了什么事,其源码如下:
public Timer(String name) {
thread.setName(name); //thread为TimerThread实例。
thread.start();
}
从上面的源代码可以知道,创建Timer对象的同时也启动了TimerThread线程。下面来看看TimerThread干了什么事:
01
public void run() {
02
03
try {
04
05
mainLoop(); //线程真正执行的代码在这个私有方法中
06
07
} finally {
08
09
// Someone killed this Thread, behave as if Timer cancelled
10
11
synchronized(queue) {
12
13
newTasksMayBeScheduled = false;
14
15
queue.clear(); // Eliminate obsolete references
16
17
}
18
19
}
20
21
}
接着来看看私有方法mainLoop()干了什么事:
01
private void mainLoop() {
02
03
while (true) {
04
05
try {
06
07
TimerTask task;
08
09
boolean taskFired; //是否已经到达Task的执行时间,如果已经到达,设置为true,否则置为false
10
11
synchronized(queue) {
12
13
// Wait for queue to become non-empty
14
15
while (queue.isEmpty() && newTasksMayBeScheduled)
16
17
queue.wait(); //由此可以看出,Timer通过wait & notify 方法安排线程之间的同步
18
19
if (queue.isEmpty())
20
21
break; // Queue is empty and will forever remain; die
22
23
24
25
// Queue nonempty; look at first evt and do the right thing