1.概要
旧的dubbo使用了Executors.newScheduledThreadPool来进行定时重试,新的提交在2018-12-11号使用了HashedWheelTimer,其原理不再解释,直接分析dubbo中的HashedWheelTimer类,如下:
-
时间轮由 HashedWheelBucket 数组构成,每个 HashedWheelBucket 维持一个双链表,双链表中的元素是HashedWheelTimeout类型
-
HashedWheelTimeout 包含TimerTask、deadline等属性
-
HashedWheelTimer只有一个工作线程,即Worker线程,worker开启后在当前tick内执行当前bucket中的task
HashedWheelTimeout也是根据tick加入到对应的bucket的,所以执行当前的tick时会执行所有符合条件的(remainingRounds=0,大于0的话需要等待对应的tick到达才可以执行,每执行一次remainingRounds减一)
-
HashedWheelTimer的使用方式:
// Step 1:创建hashedWheelTimer实例 HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(new NamedThreadFactory("DubboRegistryRetryTimer", true), retryPeriod, TimeUnit.MILLISECONDS, 128); // Step 2:创建TimerTask,以dubbo源码中的FailedRegisteredTask为例 TimerTask task = new FailedRegisteredTask(url, this); // Step 3:创建HashedWheelTimeout,即添加超时任务,并开启时间轮线程 hashedWheelTimer.newTimeout(task, 5000, TimeUnit.MILLISECONDS);
2源码分析
public class HashedWheelTimer implements Timer {
public static final String NAME = "hased";
private static final AtomicInteger INSTANCE_COUNTER = new AtomicInteger();
private static final AtomicBoolean WARNED_TOO_MANY_INSTANCES = new AtomicBoolean();
private static final int INSTANCE_COUNT_LIMIT = 64;
private static final AtomicIntegerFieldUpdater<HashedWheelTimer> WORKER_STATE_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(HashedWheelTimer.class, "workerState");
private final Worker worker = new Worker();
private final Thread workerThread;
private static final int WORKER_STATE_INIT = 0; // 0-初始化
private static final int WORKER_STATE_STARTED = 1; // 1-已启动
private static final int WORKER_STATE_SHUTDOWN = 2; // 2-关闭
private volatile int workerState;
private final long tickDuration; // 每次tick的持续时长
private final HashedWheelBucket[] wheel;
private final int mask;
private final CountDownLatch startTimeInitialized = new CountDownLatch(1);
private final Queue<HashedWheelTimeout> timeouts = new LinkedBlockingQueue<>();
private final Queue<HashedWheelTimeout> cancelledTimeouts = new LinkedBlockingQueue<>();
private final AtomicLong pendingTimeouts = new AtomicLong(0);
private final long maxPendingTimeouts;
private volatile long startTime;
// 构造函数省略......
/**
** 创建Wheel
**/
private static HashedWheelBucket[] createWheel(int ticksPerWheel) {
// 省略ticksPerWheel验证信息
// 获取标准化的wheel的大小
ticksPerWheel = normalizeTicksPerWheel(ticksPerWheel);
HashedWheelBucket[] wheel = new HashedWheelBucket[ticksPerWheel];
for (int i = 0; i < wheel.length; i++) {
// 依次创建wheel中的每个bucket
wheel[i] = new HashedWheelBucket();
}
return wheel;
}
/**
** 标准化wheel的大小,比如9,则标准化为16,17则标准化为32,34则标准化为64
**/
private static int normalizeTicksPerWheel(int ticksPerWheel) {
int normalizedTicksPerWheel = ticksPerWheel - 1;
normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 1;
normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 2;
normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 4;
normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 8;
normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 16;
return normalizedTicksPerWheel + 1;
}
public void start() {
switch (WORKER_STATE_UPDATER.get(this)) {
case WORKER_STATE_INIT:
if (WORKER_STATE_UPDATER.compareAndSet(this,WORKER_STATE_INIT,WORKER_STATE_STARTED)) {
//
workerThread.start();
}
break;
// 省略其他case
}
// Wait until the startTime is initialized by the worker.
while (startTime == 0) {
startTimeInitialized.await();
}
}
// 中断 tick 线程,即本类中的workerThread线程
@Override
public Set<Timeout> stop() {
if (Thread.currentThread() == workerThread) {
// 抛出异常:stop方法不能被取消
}
if (!WORKER_STATE_UPDATER.compareAndSet(this, WORKER_STATE_STARTED, WORKER_STATE_SHUTDOWN)) {
if (WORKER_STATE_UPDATER.getAndSet(this, WORKER_STATE_SHUTDOWN) != WORKER_STATE_SHUTDOWN) {
INSTANCE_COUNTER.decrementAndGet();
}
return Collections.emptySet();
}
try {
boolean interrupted = false;
while (workerThread.isAlive()) {
workerThread.interrupt();
try {
workerThread.join(100);
} catch (InterruptedException ignored) {
interrupted = true;
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
} finally {
INSTANCE_COUNTER.decrementAndGet();
}
return worker.unprocessedTimeouts();
}
@Override
public boolean isStop() {
return WORKER_STATE_SHUTDOWN == WORKER_STATE_UPDATER.get(this);
}
@Override
public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {
// 省略task和unit校验
long pendingTimeoutsCount = pendingTimeouts.incrementAndGet(); // 等待的timeout加1
if (maxPendingTimeouts > 0 && pendingTimeoutsCount > maxPendingTimeouts) {
pendingTimeouts.decrementAndGet();
// 抛出异常返回:等待处理的超时任务超过最大值
}
start(); // 开启时间轮线程,即workerThread线程
// deadline = 当前时间 + 任务延迟 - timer启动时间,即timer启动到任务结束的时间
long deadline = System.nanoTime() + unit.toNanos(delay) - startTime;
// 校验
if (delay > 0 && deadline < 0) {
deadline = Long.MAX_VALUE;
}
// 新建timeout,并加入到线程安全的链式队列 timeouts 中
HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline);
timeouts.add(timeout);
return timeout;
}
/**
* 返回当前Timer中pending timeouts的数量
*/
public long pendingTimeouts() {
return pendingTimeouts.get();
}
/**
** 工作线程
**/
private final class Worker implements Runnable {
// 未处理的timeout set集合
private final Set<Timeout> unprocessedTimeouts = new HashSet<Timeout>();
private long tick; // 当前已经tick的次数
@Override
public void run() {
startTime = System.nanoTime();
// 我们使用0作为未初始化的值,确定startTime若初始化即不可能为0
if (startTime == 0) {
startTime = 1;
}
// Notify the other threads waiting for the initialization at start().
startTimeInitialized.countDown();
do {
final long deadline = waitForNextTick(); // 等到当前tick的时间
if (deadline > 0) {
int idx = (int) (tick & mask); // 获取bucket的索引
processCancelledTasks();
HashedWheelBucket bucket = wheel[idx]; // 获取bucket
transferTimeoutsToBuckets(); // 需要加入bucket的timeout加入
bucket.expireTimeouts(deadline); // 遍历当前的bucket,执行完、已经取消的从链表中移除
tick++;
}
} while (WORKER_STATE_UPDATER.get(HashedWheelTimer.this) == WORKER_STATE_STARTED);
// Fill the unprocessedTimeouts so we can return them from stop() method.
for (HashedWheelBucket bucket : wheel) {
bucket.clearTimeouts(unprocessedTimeouts);
}
for (; ; ) {
HashedWheelTimeout timeout = timeouts.poll();
if (timeout == null) {
break;
}
if (!timeout.isCancelled()) {
unprocessedTimeouts.add(timeout);
}
}
processCancelledTasks();
}
private void transferTimeoutsToBuckets() {
for (int i = 0; i < 100000; i++) {
HashedWheelTimeout timeout = timeouts.poll();
if (timeout == null) {
// 所有的都已经处理过了
break;
}
if (timeout.state() == HashedWheelTimeout.ST_CANCELLED) {
continue;
}
// calculated表示当前timeout需要tick的次数
long calculated = timeout.deadline / tickDuration;
// remainingRounds表示当前timeout剩余的轮数
timeout.remainingRounds = (calculated - tick) / wheel.length;
final long ticks = Math.max(calculated, tick);
int stopIndex = (int) (ticks & mask); // 当前任务应该插入的bucket索引
HashedWheelBucket bucket = wheel[stopIndex];
bucket.addTimeout(timeout); // 插入到对应的bucket中
}
}
// 处理取消的timeout
private void processCancelledTasks() {
for (; ; ) {
HashedWheelTimeout timeout = cancelledTimeouts.poll();
if (timeout == null) {
// 所有的都已经处理过了
break;
}
timeout.remove();
}
}
/**
** 根据 startTime 和当前 tick 的次数计算目标nanoTime,然后等到目标nanoTime为止
**/
private long waitForNextTick() {
long deadline = tickDuration * (tick + 1);
for (; ; ) {
final long currentTime = System.nanoTime() - startTime;
// 需要睡眠的时间
long sleepTimeMs = (deadline - currentTime + 999999) / 1000000;
if (sleepTimeMs <= 0) {
if (currentTime == Long.MIN_VALUE) {
return -Long.MAX_VALUE;
} else {
return currentTime;
}
}
// 当前环境是windows环境
if (isWindows()) {
sleepTimeMs = sleepTimeMs / 10 * 10;
}
try {
// 睡眠sleepTimeMs
Thread.sleep(sleepTimeMs);
} catch (InterruptedException ignored) {
// 如果收到shutdown请求返回Long.MIN_VALUE
if (WORKER_STATE_UPDATER.get(HashedWheelTimer.this) == WORKER_STATE_SHUTDOWN) {
return Long.MIN_VALUE;
}
} // try
}
}
Set<Timeout> unprocessedTimeouts() {
return Collections.unmodifiableSet(unprocessedTimeouts);
}
}
private static final class HashedWheelTimeout implements Timeout {
private static final int ST_INIT = 0;
private static final int ST_CANCELLED = 1;
private static final int ST_EXPIRED = 2;
private static final AtomicIntegerFieldUpdater<HashedWheelTimeout> STATE_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(HashedWheelTimeout.class, "state");
private final HashedWheelTimer timer;
private final TimerTask task;
private final long deadline;
private volatile int state = ST_INIT;
// 计算剩余的轮数, 只有timer走够轮数, 并且到达了task所在的slot, task 才会过期
long remainingRounds;
HashedWheelTimeout next;
HashedWheelTimeout prev;
// 当前timeout所有的bucket
HashedWheelBucket bucket;
HashedWheelTimeout(HashedWheelTimer timer, TimerTask task, long deadline) {
this.timer = timer;
this.task = task;
this.deadline = deadline;
}
@Override
public Timer timer() {
return timer;
}
@Override
public TimerTask task() {
return task;
}
/**
** 把当前的timeout设置为已取消
**/
@Override
public boolean cancel() {
// only update the state it will be removed from HashedWheelBucket on next tick.
if (!compareAndSetState(ST_INIT, ST_CANCELLED)) {
return false;
}
timer.cancelledTimeouts.add(this);
return true;
}
void remove() {
HashedWheelBucket bucket = this.bucket;
if (bucket != null) {
// 从当前bucket移除
bucket.remove(this);
} else {
timer.pendingTimeouts.decrementAndGet();
}
}
public boolean compareAndSetState(int expected, int state) {
return STATE_UPDATER.compareAndSet(this, expected, state);
}
public int state() {
return state;
}
// 当前timeout是否已取消
@Override
public boolean isCancelled() {
return state() == ST_CANCELLED;
}
// 当前timeout是否已过期
@Override
public boolean isExpired() {
return state() == ST_EXPIRED;
}
public void expire() {
// 先设置当前timeout的状态为已过期状态
if (!compareAndSetState(ST_INIT, ST_EXPIRED)) {
return;
}
task.run(this);
}
// 省略toString方法
}
private static final class HashedWheelBucket {
private HashedWheelTimeout head; // 头结点
private HashedWheelTimeout tail; // 尾结点
/**
** 将新的timeout插入链表的尾部,
**/
void addTimeout(HashedWheelTimeout timeout) {
assert timeout.bucket == null;
timeout.bucket = this;
if (head == null) {
head = tail = timeout;
} else {
tail.next = timeout;
timeout.prev = tail;
tail = timeout;
}
}
/**
** 遍历当前的bucket,执行完、已经取消的从链表中移除
**/
void expireTimeouts(long deadline) {
HashedWheelTimeout timeout = head;
while (timeout != null) {
HashedWheelTimeout next = timeout.next;
if (timeout.remainingRounds <= 0) {
// timer走够了轮数,并且到达该bucket,则移除timeout
next = remove(timeout);
if (timeout.deadline <= deadline) {
// 过期
timeout.expire();
} else {
// 异常,timeout放错了bucket,不可能发生的情况
}
} else if (timeout.isCancelled()) {
// timeout已经取消了,移除
next = remove(timeout);
} else {
timeout.remainingRounds--;
}
// timeout指向下一个
timeout = next;
}
}
public HashedWheelTimeout remove(HashedWheelTimeout timeout) {
HashedWheelTimeout next = timeout.next;
// 断开timeout的prev,同时使用timeout的prev指向timeout的next
if (timeout.prev != null) {
timeout.prev.next = next;
}
// 断开timeout的next,同时使用timeout.next的prev指向timeout的prev
if (timeout.next != null) {
timeout.next.prev = timeout.prev;
}
// timeout是head的情况下,特殊处理
if (timeout == head) {
if (timeout == tail) {
tail = null;
head = null;
} else {
head = next;
}
} else if (timeout == tail) {
tail = timeout.prev;
}
timeout.prev = null;
timeout.next = null;
timeout.bucket = null;
// 当前等待的timeout减一,即HashedWheelTimer中的pendingTimeouts属性减一
timeout.timer.pendingTimeouts.decrementAndGet();
return next;
}
/**
* 清空bucket,并返回不是过期/取消的Timeout
*/
void clearTimeouts(Set<Timeout> set) {
for (; ; ) {
HashedWheelTimeout timeout = pollTimeout();
if (timeout == null) {
return;
}
if (timeout.isExpired() || timeout.isCancelled()) {
continue;
}
set.add(timeout);
}
}
// 清空bucket
private HashedWheelTimeout pollTimeout() {
HashedWheelTimeout head = this.head;
if (head == null) {
return null;
}
HashedWheelTimeout next = head.next;
if (next == null) {
tail = this.head = null;
} else {
this.head = next;
next.prev = null;
}
head.next = null;
head.prev = null;
head.bucket = null;
return head;
}
} // HashedWheelBucket结束
//......
}