目录
1.基本概念
1.Timer
Timer用来调度和管理定时任务,提供定时任务的添加、删除、停止、运行等方法
public interface Timer {
Timeout newTimeout(TimerTask task, long delay, TimeUnit unit);
Set<Timeout> stop();
boolean isStop();
}
2.Timeout
Timeout持有TimerTask,用来处理定时任务
public interface Timeout {
Timer timer(); // 绑定的定时器
TimerTask task(); // 绑定的定时任务
boolean isExpired(); // 判断过期
boolean isCancelled(); // 判断取消
boolean cancel(); // 进行取消
}
3.TimerTask
TimerTask就是一个定时任务
public interface TimerTask {
void run(Timeout timeout) throws Exception;
}
2.HashedWheelTimeout
1.类结构分析
private static final class HashedWheelTimeout implements Timeout {
// 当前Timeout状态
private static final int ST_INIT = 0; // 初始化
private static final int ST_CANCELLED = 1; // 取消
private static final int ST_EXPIRED = 2; // 过期
// state成员变量的更新器
private static final AtomicIntegerFieldUpdater<HashedWheelTimeout> STATE_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(HashedWheelTimeout.class, "state");
private final HashedWheelTimer timer; // 绑定的定时器
private final TimerTask task; // 绑定的任务
private final long deadline; // 这个Timeout处理任务的deadline
@SuppressWarnings({"unused", "FieldMayBeFinal", "RedundantFieldInitialization"})
private volatile int state = ST_INIT;
long remainingRounds; // 剩余的圈数 当剩余圈数不大于0时 当前Timeout才能去执行任务
// 维护双链表的指针
HashedWheelTimeout next;
HashedWheelTimeout prev;
HashedWheelBucket bucket; // 用来保存当前Timeout的桶
HashedWheelTimeout(HashedWheelTimer timer, TimerTask task, long deadline) {
this.timer = timer;
this.task = task;
this.deadline = deadline;
}
...
}
2.remove()
void remove() {
// 将当前Timeout从保存它的桶中移除 具体看下面HashedWheelBucket分析
HashedWheelBucket bucket = this.bucket;
if (bucket != null) {
bucket.remove(this);
} else {
timer.pendingTimeouts.decrementAndGet();
}
}
3.expire()
public void expire() {
// 通过UPDATER修改state为expired状态 修改失败直接return
if (!compareAndSetState(ST_INIT, ST_EXPIRED)) {
return;
}
try {
// 执行任务 具体可以参考RetryTimerTask#run()
task.run(this);
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn("An exception was thrown by " + TimerTask.class.getSimpleName() + '.', t);
}
}
}
3.HashedWheelBucket
1.addTimeout()
注意啦!!Timeout一开始是放在队列中的,并不是在时间轮上,是在Tick触发时才将队列中的元素散列到时间轮底层的桶上
void addTimeout(HashedWheelTimeout timeout) {
assert timeout.bucket == null;
// 设置当前Timeout的bucket
timeout.bucket = this;
// 双向链表维护
if (head == null) {
head = tail = timeout;
} else {
tail.next = timeout;
timeout.prev = tail;
tail = timeout;
}
}
public HashedWheelTimeout remove(