一、案例分析
public void testExecutionOnTaskExecutor() throws InterruptedException {
int timeout = 10;
final CountDownLatch latch = new CountDownLatch(1);
final CountDownLatch timeoutLatch = new CountDownLatch(1);
Executor executor = new Executor() {
@Override
public void execute(Runnable command) {
try {
command.run();
} finally {
latch.countDown();
}
}
};
final HashedWheelTimer timer = new HashedWheelTimer(Executors.defaultThreadFactory(), 100,
TimeUnit.MILLISECONDS, 32, true, 2, executor);
timer.newTimeout(new TimerTask() {
@Override
public void run(final Timeout timeout) throws Exception {
timeoutLatch.countDown();
}
}, timeout, TimeUnit.MILLISECONDS);
latch.await();
timeoutLatch.await();
timer.stop();
}
二、底层接口
public interface Timer {
/**
* Schedules the specified {@link TimerTask} for one-time execution after
* the specified delay.
*
* @return a handle which is associated with the specified task
*
* @throws IllegalStateException if this timer has been {@linkplain #stop() stopped} already
* @throws RejectedExecutionException if the pending timeouts are too many and creating new timeout
* can cause instability in the system.
*/
Timeout newTimeout(TimerTask task, long delay, TimeUnit unit);
/**
* Releases all resources acquired by this {@link Timer} and cancels all
* tasks which were scheduled but not executed yet.
*
* @return the handles associated with the tasks which were canceled by
* this method
*/
Set<Timeout> stop();
}
newTimeOut: 提交任务,并在延迟delay的unit单位时间后,执行任务
stop:取消所有调度中但是未执行的任务
三、构建hashWheel函数
public HashedWheelTimer(
ThreadFactory threadFactory,
long tickDuration, TimeUnit unit, int ticksPerWheel, boolean leakDetection,
long maxPendingTimeouts, Executor taskExecutor)
threadFactory:线程工厂,用于创建工作线程
tickDuration:每次转动的间隔的时间
unit:每次转动的间隔的时间的时间单元
ticksPerWheel:时间轮上一共有多少个 slot,默认 512 个。分配的 slot 越多,占用的内存空间就越大
leakDetection:是否开启内存泄漏检测
maxPendingTimeouts:最大等待任务数
taskExecutor:任务处理器
3.1 HashedWheelBucket[] wheel
// 时间轮的环形数组
wheel = createWheel(ticksPerWheel);
private static HashedWheelBucket[] createWheel(int ticksPerWheel) {
//ticksPerWheel may not be greater than 2^30
checkInRange(ticksPerWheel, 1, 1073741824, "ticksPerWheel");
ticksPerWheel = normalizeTicksPerWheel(ticksPerWheel);
HashedWheelBucket[] wheel = new HashedWheelBucket[ticksPerWheel];
for (int i = 0; i < wheel.length; i ++) {
wheel[i] = new HashedWheelBucket();
}
return wheel;
}
private static final class HashedWheelBucket {
// Used for the linked-list dat