java timer 原理_java线程之Timer实现原理解析

1. 整体图解

855cda2e4bcd?utm_campaign

整体结构图解

2. 包含任务执行逻辑的 TimerTask 抽象类

任务抽象类 TimerTask 的生命周期表示如下:

855cda2e4bcd?utm_campaign

TimerTask的生命周期

任务抽象类 TimerTask 的属性详细解释如下:

855cda2e4bcd?utm_campaign

TimerTask类的属性解析

任务抽象类 TimerTask 的实例方法:

855cda2e4bcd?utm_campaign

TimerTask类的实例方法

3. 任务队列 TaskQueue 类

TaskQueue 内部采用最小堆来实现优先队列, 其各种操作的复杂度不超过O(logn)

TaskQueue 类的属性

855cda2e4bcd?utm_campaign

TaskQueue类的属性

TaskQueue 类的实例方法

855cda2e4bcd?utm_campaign

TaskQueue类的实例方法

855cda2e4bcd?utm_campaign

TaskQueue类的实例方法

855cda2e4bcd?utm_campaign

TaskQueue类的实例方法

855cda2e4bcd?utm_campaign

辅助方法来维持最小堆的性质

4. 执行任务的线程类 TimerThread

执行任务的线程类 TimerThread 继承 Thread 类, 用来执行任务队列中的任务, 因此, Timer 类调度的所有任务都是在单线程中按执行时间先后顺序执行的

TimerThread 类的属性

855cda2e4bcd?utm_campaign

TimerThread类的属性

TimerThread 类的实例方法

855cda2e4bcd?utm_campaign

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 类的属性

855cda2e4bcd?utm_campaign

Timer类的属性

Timer 类的构造方法

855cda2e4bcd?utm_campaign

Timer类的构造方法

Timer 类的 cancel() 方法

855cda2e4bcd?utm_campaign

cancel方法

schedule 系列方法

855cda2e4bcd?utm_campaign

schedule系列方法

scheduleAtFixedRate 系列方法

855cda2e4bcd?utm_campaign

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 方法具有追赶性;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值