HashedWheelTimer源码浅析

HashedWheelTimer由HashedWheelBucket数组组成,通过newTimeout方法提交任务并启动Worker工作线程,工作线程会不断将新的Timeout加到HashedWheelBucket中,并执行HashedWheelBucket中的Timeout。

1.Timeout

通过Timeout可以获取关联的Timer和TimerTask。

public interface Timeout {
    Timer timer();
    TimerTask task();
    boolean isExpired();
    boolean isCancelled();
    boolean cancel();
}

2.HashedWheelTimeout

HashedWheelTimeout还可以获取前一个或者后一个Timeout。

private static final class HashedWheelTimeout implements Timeout {

	private final HashedWheelTimer timer;
    private final TimerTask task;
    private final long deadline;
    private volatile int state = ST_INIT;
    long remainingRounds;
    HashedWheelTimeout next;
    HashedWheelTimeout prev;
    HashedWheelBucket bucket;
    
    HashedWheelTimeout(HashedWheelTimer timer, TimerTask task, long deadline) {
        this.timer = timer;
        this.task = task;
        this.deadline = deadline;
    }
    
    @Override
    public boolean cancel() {
        if (!compareAndSetState(ST_INIT, ST_CANCELLED)) {
            return false;
        }
        // 将Timeout加入队列中
        timer.cancelledTimeouts.add(this);
        return true;
    }
    
    // 移除该Timeout并且pendingTimeouts减一
    void remove() {
        HashedWheelBucket bucket = this.bucket;
        if (bucket != null) {
            bucket.remove(this);
        } else {
            timer.pendingTimeouts.decrementAndGet();
        }
    }
    
    // 执行任务
    public void expire() {
        if (!compareAndSetState(ST_INIT, ST_EXPIRED)) {
            return;
        }

        try {
            task.run(this);
        } catch (Throwable t) {
            if (logger.isWarnEnabled()) {
                logger.warn("An exception was thrown by " + TimerTask.class.getSimpleName() + '.', t);
            }
        }
    }
}

3.HashedWheelBucket

HashedWheelBucket是用来存储HashedWheelTimeouts的双向链表。

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;
        }
    }
    
    // 处理所有的Timeout
    void expireTimeouts(long deadline) {
        HashedWheelTimeout timeout = head;

        while (timeout != null) {
            HashedWheelTimeout next = timeout.next;
            if (timeout.remainingRounds <= 0) {
                next = remove(timeout);
                if (timeout.deadline <= deadline) {
                    timeout.expire();
                } else {
                    throw new IllegalStateException(String.format(
                        "timeout.deadline (%d) > deadline (%d)", timeout.deadline, deadline));
                }
            } else if (timeout.isCancelled()) {
               	// 移除timeout并返回其下一个节点
                next = remove(timeout);
            } else {
                timeout.remainingRounds--;
            }
            timeout = next;
        }
    }
    
}

4.HashedWheelTimer

public class HashedWheelTimer implements Timer {
    
    // 工作线程
    private final Worker worker = new Worker();
    private final Thread workerThread;
    
    // 工作状态 0 - init, 1 - started, 2 - shut down
    private volatile int workerState;
    
    // Timeout队列
    private final Queue<HashedWheelTimeout> timeouts = new LinkedBlockingQueue<>();
    private final Queue<HashedWheelTimeout> cancelledTimeouts = new LinkedBlockingQueue<>();
    
    // Timeouts数量
    private final AtomicLong pendingTimeouts = new AtomicLong(0);
    private final long maxPendingTimeouts;
}
public HashedWheelTimer(
        ThreadFactory threadFactory,
        long tickDuration, TimeUnit unit, int ticksPerWheel,
        long maxPendingTimeouts) {

    if (threadFactory == null) {
        throw new NullPointerException("threadFactory");
    }
    if (unit == null) {
        throw new NullPointerException("unit");
    }
    if (tickDuration <= 0) {
        throw new IllegalArgumentException("tickDuration must be greater than 0: " + tickDuration);
    }
    if (ticksPerWheel <= 0) {
        throw new IllegalArgumentException("ticksPerWheel must be greater than 0: " + ticksPerWheel);
    }

    // 创建Bucket数组,初始化时间轮
    wheel = createWheel(ticksPerWheel);
    mask = wheel.length - 1;

    this.tickDuration = unit.toNanos(tickDuration);

    if (this.tickDuration >= Long.MAX_VALUE / wheel.length) {
        throw new IllegalArgumentException(String.format(
                "tickDuration: %d (expected: 0 < tickDuration in nanos < %d",
                tickDuration, Long.MAX_VALUE / wheel.length));
    }
    // 创建工作线程
    workerThread = threadFactory.newThread(worker);

    this.maxPendingTimeouts = maxPendingTimeouts;

    if (INSTANCE_COUNTER.incrementAndGet() > INSTANCE_COUNT_LIMIT &&
            WARNED_TOO_MANY_INSTANCES.compareAndSet(false, true)) {
        reportTooManyInstances();
    }
}
// 提交新任务并返回关联的Timeout
public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {
    if (task == null) {
        throw new NullPointerException("task");
    }
    if (unit == null) {
        throw new NullPointerException("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 + ")");
    }

    // 如果工作状态是0改为1并启动工作线程。等待工作线程初始化startTime.
    start();

    long deadline = System.nanoTime() + unit.toNanos(delay) - startTime;

    if (delay > 0 && deadline < 0) {
        deadline = Long.MAX_VALUE;
    }
    HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline);
    timeouts.add(timeout);
    return timeout;
}

5.Worker

private final class Worker implements Runnable {
        private final Set<Timeout> unprocessedTimeouts = new HashSet<Timeout>();
        private long tick;   
}
public void run() {
    // 初始化startTime.
    startTime = System.nanoTime();
    if (startTime == 0) {
        // 0表示没初始化,初始化了就不是0
        startTime = 1;
    }

    // 通知start()方法中等待初始化startTime的线程
    startTimeInitialized.countDown();

    // 只要工作状态是1就一直循环
    do {
        final long deadline = waitForNextTick();
        if (deadline > 0) {
            int idx = (int) (tick & mask);
            // 移除取消的任务
            processCancelledTasks();
            // 获取要处理的Bucket
            HashedWheelBucket bucket =
                    wheel[idx];
            // 从timeouts中取出Timeout并加入到对应的Bucket中
            transferTimeoutsToBuckets();
            // 执行Bucket中的任务
            bucket.expireTimeouts(deadline);
            tick++;
        }
    } while (WORKER_STATE_UPDATER.get(HashedWheelTimer.this) == WORKER_STATE_STARTED);

    // 清理Bucket并将不是expired或cancelled的Timeout加入到unprocessedTimeouts中
    for (HashedWheelBucket bucket : wheel) {
        bucket.clearTimeouts(unprocessedTimeouts);
    }
    for (; ; ) {
        HashedWheelTimeout timeout = timeouts.poll();
        if (timeout == null) {
            break;
        }
        if (!timeout.isCancelled()) {
            unprocessedTimeouts.add(timeout);
        }
    }
    processCancelledTasks();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值