26
27
long currentTime, executionTime;
28
29
task = queue.getMin();
30
31
synchronized(task.lock) {
32
33
if (task.state == TimerTask.CANCELLED) {
34
35
queue.removeMin();
36
37
continue; // No action required, poll queue again
38
39
}
40
41
currentTime = System.currentTimeMillis();
42
43
executionTime = task.nextExecutionTime;
44
45
if (taskFired = (executionTime<=currentTime)) { //Task的执行时间已到,设置taskFired为true
46
47
if (task.period == 0) { // Non-repeating, remove
48
49
queue.removeMin(); //移除队列中的当前任务
50
51
task.state = TimerTask.EXECUTED;
52
53
} else { // Repeating task, reschedule
54
55
queue.rescheduleMin( //重新设置任务的下一次执行时间
56
57
task.period<0 currentTime - task.period
58
59
: executionTime + task.period);
60
61
}
62
63
}
64
65
}
66
67
if (!taskFired) // Task hasn't yet fired; wait
68
69
queue.wait(executionTime - currentTime); //还没有执行时间,通过wait等待特定时间
70
71
}
72
73
if (taskFired) // Task fired; run it, holding no locks
74
75
task.run(); //已经到达执行时间,执行任务
76
77
} catch(InterruptedException e) {
78
79
}
80
81
}
82
83
}
也就是说,一旦创建了Timer类的实例,就一直存在一个循环在遍历queue中的任务,如果有任务的话,就通过thread去执行该任务,否则线程通过wait()方法阻塞自己,由于没有任务在队列中,就没有必要继续thread中的循环。
上面提到,如果Timer的任务队列中不包含任务时,Timer中的TimerThread线程并不会执行,接着来看看为Timer添加任务后会出现怎样的情况。为Timer添加任务就是timer.schedule()干的事,schedule()方法直接调用Timer的私有方法 sched(),sched()是真正安排Task的地方,其源代码如下:
01
private void sched(TimerTask task, long time, long period) {
02
03
if (time < 0)
04
05
throw new IllegalArgumentException("Illegal execution time.");
06
07
08
09
synchronized(queue) {
10
11
if (!thread.newTasksMayBeScheduled)
12
13
throw new IllegalStateException("Timer already cancelled.");
14
15
16
17
synchronized(task.lock) {
18
19
if (task.state != TimerTask.VIRGIN) //我喜欢virgin状态,其他状态表明该Task已经被schedule过了
20
21
throw new IllegalStateException(
22
23
"Task already scheduled or cancelled");
24
25
26
27
//设置Task下一次应该执行的时间, 由System.currentTimeMillis()+/-delay得到
28
29
task.nextExecutionTime = time;
30
31
task.period = period;
32
33
task.state = TimerTask.SCHEDULED;
34
35
}
36
37
38
39
queue.add(task); //queue为TaskQueue类的实例,添加任务到队列中
40
41
if (queue.getMin() == task) //获取队列中nextExecutionTime最小的任务,如果与当前任务相同
42
43
queue.notify(