1. 整体图解
整体结构图解
2. 包含任务执行逻辑的 TimerTask 抽象类
任务抽象类 TimerTask 的生命周期表示如下:
TimerTask的生命周期
任务抽象类 TimerTask 的属性详细解释如下:
TimerTask类的属性解析
任务抽象类 TimerTask 的实例方法:
TimerTask类的实例方法
3. 任务队列 TaskQueue 类
TaskQueue 内部采用最小堆来实现优先队列, 其各种操作的复杂度不超过O(logn)
TaskQueue 类的属性
TaskQueue类的属性
TaskQueue 类的实例方法
TaskQueue类的实例方法
TaskQueue类的实例方法
TaskQueue类的实例方法
辅助方法来维持最小堆的性质
4. 执行任务的线程类 TimerThread
执行任务的线程类 TimerThread 继承 Thread 类, 用来执行任务队列中的任务, 因此, Timer 类调度的所有任务都是在单线程中按执行时间先后顺序执行的
TimerThread 类的属性
TimerThread类的属性
TimerThread 类的实例方法
run方法
mainloop 方法详细解释如下:
private void mainLoop() {
while (true) {
try {
TimerTask task;
boolean taskFired;
synchronized (queue) {
// 任务队列为空, 让当前执行线程放弃queue锁
while (queue.isEmpty() && newTasksMayBeScheduled) {
queue.wait();
}
// 执行期间发现任务队列为空, 即没有任务需要执行, 因此跳出循环
if (queue.isEmpty()) {
break;
}
long currentTime, executionTime;
task = queue.getMin();
synchronized (task.lock) {
if (task.state == TimerTask.TimerTaskStatus.CANCELLED) {
queue.removeMin();
continue; // 开始下一次循环去执行下一个任务
}
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime <= currentTime)) { // 任务的开始时间早于当前时间, 则立即执行
if (task.period == 0) { // 非周期型任务
queue.removeMin();
task.state = TimerTask.TimerTaskStatus.EXECUTED;
} else { // 周期型任务
// schedule 与 scheduleAtFixedRate 的区别体现在这里
// 当执行时间早于当前时间时, schedule系列方法执行时没有追赶性, scheduleAtFixedRate系列方法执行时具有追赶性
queue.rescheduleMin(task.period < 0 ? currentTime - task.period : executionTime + task.period);
}
}
}
if (!taskFired) { // 还未到时间执行任务
queue.wait(executionTime - currentTime);
}
}
if (taskFired) { // 可以执行任务(注意: 没有锁)
task.run();
}
} catch (InterruptedException e) {
}
}
}
5. Timer 类解析
Timer 类的属性
Timer类的属性
Timer 类的构造方法
Timer类的构造方法
Timer 类的 cancel() 方法
cancel方法
schedule 系列方法
schedule系列方法
scheduleAtFixedRate 系列方法
scheduleAtFixedRate系列方法
schedule 和 scheduleAtFixedRate 方法的具体执行逻辑放在 sched 方法上:
private void sched(TimerTask task, long time, long period) {
// 验证参数是否正确
if (time < 0) {
throw new IllegalArgumentException("Illegal execution time.");
}
if (Math.abs(period) > (Long.MAX_VALUE >> 1)) {
period >>= 1;
}
// 将任务task的属性设置好并存放在任务队列queue上
synchronized (queue) {
if (!thread.newTasksMayBeScheduled) {
throw new IllegalArgumentException("Timer already cancelled.");
}
synchronized (task.lock) {
if (task.state != TimerTask.TimerTaskStatus.VIRGIN) {
throw new IllegalArgumentException("Task already scheduled or cancelled!");
}
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.TimerTaskStatus.SCHEDULED;
}
queue.add(task);
// 若加入任务前队列为空则要通知执行任务的线程, 使其从WAITING状态切换为RUNNABLE状态
if (queue.getMin() == task) {
queue.notify();
}
}
}
注意: schedule 和 scheduleAtFixedRate 方法的区别在于当执行时间早于当前时间时, schedule 方法不具有追赶性, 而 scheduleAtFixedRate 方法具有追赶性;