一、前言
之前一直研究延迟队列的时间方式,调研过挺多技术,Netty中提供的HashedWheelTimer时间轮算法的实现也是其中一种。
于是就研究了下内部实现的原理,研究的代码的版本如下:
<groupId>io.netty</groupId>
<artifactId>netty-parent</artifactId>
<version>5.0.0.Final-SNAPSHOT</version>
二、类介绍
1. 构造方法
public HashedWheelTimer(
ThreadFactory threadFactory,
long tickDuration,
TimeUnit unit,
int ticksPerWheel,
boolean leakDetection,
long maxPendingTimeouts){
}
- threadFactory:线程工厂,用于创建工作线程
- tickDuration和unit:时间刻度的长度,多久tick一次
- ticksPerWheel:时间轮的长度,一圈下来有多少格
- leakDetection:默认为true,开启泄漏检测
- maxPendingTimeouts:最大挂起Timeouts数量
2. 成员变量
2.1 内部类 Worker
worker工作线程主要负责任务调度触发,单线程运行。
2.2 内部类 HashedWheelBucket
时间轮上面的格子,内部持有HashedWheelTimeout组成的链表结构的头尾节点,多个格子组成的时间轮形成一圈又一圈的任务环
2.3 内部类 HashedWheelTimeout
往时间轮里面提交的任务会被封装成HashedWheelTimeout
3. 源码解析
3.1 添加任务:newTimeout方法
public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {
requireNonNull(task, "taks");
requireNonNull(unit, "unit");
long pendingTimeoutsCount = pendingTimeouts.incrementAndGet();
if (maxPendingTimeouts > 0 && pendingTimeoutsCount > maxPendingTimeouts) {
pendingTimeouts.decrementAndGet();
throw new RejectedExecutionException("Number of pending timeouts
(" + pendingTimeoutsCount + ") is greater than or equal to
maximum allowed pending " + "timeouts (" + maxPendingTimeouts + ")");
}
start();
// Add the timeout to the timeout queue which will be processed on the next tick.
// During processing all the queued HashedWheelTimeouts will be added to the correct HashedWheelBucket.
long deadline = System.nanoTime() + unit.toNanos(delay) - startTime;
// Guard against overflow.
if (delay > 0 && deadline < 0) {
deadline = Long.MAX_VALUE;
}
HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline);