All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dromara.hutool.cron.timingwheel.TimingWheel Maven / Gradle / Ivy

There is a newer version: 6.0.0.M3
Show newest version
/*
 * Copyright (c) 2013-2024 Hutool Team and hutool.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dromara.hutool.cron.timingwheel;

import org.dromara.hutool.log.LogUtil;

import java.util.function.Consumer;

/**
 * 多层时间轮,常用于延时任务。
* 时间轮是一种环形数据结构,由多个槽组成,每个槽中存放任务集合。
* 一个单独的线程推进时间一槽一槽的移动,并执行槽中的任务。 * * @author eliasyaoyc, looly */ public class TimingWheel { /** * 一个时间槽的范围 */ private final long tickMs; /** * 时间轮大小,时间轮中时间槽的个数 */ private final int wheelSize; /** * 时间跨度,当前时间轮总间隔,即单个槽的跨度*槽个数 */ private final long interval; /** * 时间槽 */ private final TimerTaskList[] timerTaskLists; /** * 当前时间,指向当前操作的时间格,代表当前时间 */ private long currentTime; /** * 上层时间轮 */ private volatile TimingWheel overflowWheel; /** * 任务处理器 */ private final Consumer consumer; /** * 构造 * * @param tickMs 一个时间槽的范围,单位毫秒 * @param wheelSize 时间轮大小 * @param consumer 任务处理器 */ public TimingWheel(final long tickMs, final int wheelSize, final Consumer consumer) { this(tickMs, wheelSize, System.currentTimeMillis(), consumer); } /** * 构造 * * @param tickMs 一个时间槽的范围,单位毫秒 * @param wheelSize 时间轮大小 * @param currentTime 当前时间 * @param consumer 任务处理器 */ public TimingWheel(final long tickMs, final int wheelSize, final long currentTime, final Consumer consumer) { this.tickMs = tickMs; this.wheelSize = wheelSize; this.interval = tickMs * wheelSize; this.timerTaskLists = new TimerTaskList[wheelSize]; for (int i = 0; i < wheelSize; i++) { this.timerTaskLists[i] = new TimerTaskList(); } //currentTime为tickMs的整数倍 这里做取整操作 this.currentTime = currentTime - (currentTime % tickMs); this.consumer = consumer; } /** * 添加任务到时间轮 * * @param timerTask 任务 * @return 是否成功 */ public boolean addTask(final TimerTask timerTask) { final long expiration = timerTask.getDelayMs(); //过期任务直接执行 if (expiration < currentTime + tickMs) { return false; } else if (expiration < currentTime + interval) { //当前时间轮可以容纳该任务 加入时间槽 final long virtualId = expiration / tickMs; final int index = (int) (virtualId % wheelSize); LogUtil.debug("tickMs: {} ------index: {} ------expiration: {}", tickMs, index, expiration); final TimerTaskList timerTaskList = timerTaskLists[index]; timerTaskList.addTask(timerTask); if (timerTaskList.setExpiration(virtualId * tickMs)) { //添加到delayQueue中 consumer.accept(timerTaskList); } } else { //放到上一层的时间轮 final TimingWheel timeWheel = getOverflowWheel(); timeWheel.addTask(timerTask); } return true; } /** * 推进时间 * * @param timestamp 推进的时间 */ public void advanceClock(final long timestamp) { if (timestamp >= currentTime + tickMs) { currentTime = timestamp - (timestamp % tickMs); if (overflowWheel != null) { //推进上层时间轮时间 this.getOverflowWheel().advanceClock(timestamp); } } } /** * 创建或者获取上层时间轮 */ private TimingWheel getOverflowWheel() { if (overflowWheel == null) { synchronized (this) { if (overflowWheel == null) { overflowWheel = new TimingWheel(interval, wheelSize, currentTime, consumer); } } } return overflowWheel; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy