国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【算法數(shù)據(jù)結(jié)構(gòu)專題】「延時(shí)隊(duì)列算法」史上手把手教你針對(duì)層級(jí)時(shí)間輪(TimingWheel)實(shí)現(xiàn)延時(shí)隊(duì)列的開(kāi)發(fā)實(shí)戰(zhàn)落地(下)

這篇具有很好參考價(jià)值的文章主要介紹了【算法數(shù)據(jù)結(jié)構(gòu)專題】「延時(shí)隊(duì)列算法」史上手把手教你針對(duì)層級(jí)時(shí)間輪(TimingWheel)實(shí)現(xiàn)延時(shí)隊(duì)列的開(kāi)發(fā)實(shí)戰(zhàn)落地(下)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

承接上文

承接上一篇文章【算法數(shù)據(jù)結(jié)構(gòu)專題】「延時(shí)隊(duì)列算法」史上手把手教你針對(duì)層級(jí)時(shí)間輪(TimingWheel)實(shí)現(xiàn)延時(shí)隊(duì)列的開(kāi)發(fā)實(shí)戰(zhàn)落地(上)】我們基本上對(duì)層級(jí)時(shí)間輪算法的基本原理有了一定的認(rèn)識(shí),本章節(jié)就從落地的角度進(jìn)行分析和介紹如何通過(guò)Java進(jìn)行實(shí)現(xiàn)一個(gè)屬于我們自己的時(shí)間輪服務(wù)組件,最后,在告訴大家一下,其實(shí)時(shí)間輪的技術(shù)是來(lái)源于生活中的時(shí)鐘。

時(shí)間輪演示結(jié)構(gòu)總覽

無(wú)序列表時(shí)間輪

【無(wú)序列表時(shí)間輪】主要是由LinkedList鏈表和啟動(dòng)線程、終止線程實(shí)現(xiàn)。

遍歷定時(shí)器中所有節(jié)點(diǎn),將剩余時(shí)間為 0s 的任務(wù)進(jìn)行過(guò)期處理,在執(zhí)行一個(gè)周期。

  • 無(wú)序鏈表:每一個(gè)延時(shí)任務(wù)都存儲(chǔ)在該鏈表當(dāng)中(無(wú)序存儲(chǔ))。
  • 啟動(dòng)線程: 直接在鏈表后面push ,時(shí)間復(fù)雜度 O(1)。
  • 終止線程: 直接在鏈表中刪除節(jié)點(diǎn),時(shí)間復(fù)雜度 O(1) 。

遍歷周期:需要遍歷鏈表中所有節(jié)點(diǎn),時(shí)間復(fù)雜度 O(n),所以伴隨著鏈表中的元素越來(lái)越多,速度也會(huì)越來(lái)越慢!

無(wú)序列表時(shí)間輪的長(zhǎng)度限制了其適用場(chǎng)景,這里對(duì)此進(jìn)行優(yōu)化。因此引入了有序列表時(shí)間輪。

有序列表時(shí)間輪

與無(wú)序列表時(shí)間輪一樣,同樣使用鏈表進(jìn)行實(shí)現(xiàn)和設(shè)計(jì),但存儲(chǔ)的是絕對(duì)延時(shí)時(shí)間點(diǎn)

  • 啟動(dòng)線程有序插入,比較時(shí)間按照時(shí)間大小有序插入,時(shí)間復(fù)雜度O(n),主要耗時(shí)在插入操作。
  • 終止線程鏈表中查找任務(wù),刪除節(jié)點(diǎn),時(shí)間復(fù)雜度O(n),主要耗時(shí)在插入操作

找到執(zhí)行最后一個(gè)過(guò)期任務(wù)即可,無(wú)需遍歷整個(gè)鏈表,時(shí)間復(fù)雜度 O(1),從上面的描述「有序列表定時(shí)器」的性能瓶頸在于插入時(shí)的任務(wù)排序,但是換來(lái)的就是縮短了遍歷周期。

所以我們?nèi)绻岣咝?,就必須要提升一下插入和刪除以及檢索的性能,因此引入了「樹(shù)形有序列表時(shí)間輪」在「有序列表定時(shí)器」的基礎(chǔ)上進(jìn)行優(yōu)化,以有序樹(shù)的形式進(jìn)行任務(wù)存儲(chǔ)。

樹(shù)形有序列表時(shí)間輪

  • 啟動(dòng)定時(shí)器: 有序插入,比較時(shí)間按照時(shí)間大小有序插入,時(shí)間復(fù)雜度 O(logn)
  • 終止定時(shí)器: 在鏈表中查找任務(wù),刪除節(jié)點(diǎn),時(shí)間復(fù)雜度 O(logn)
  • 周期清算: 找到執(zhí)行最后一個(gè)過(guò)期任務(wù)即可,無(wú)需遍歷整個(gè)鏈表,時(shí)間復(fù)雜度 O(1)

層級(jí)時(shí)間輪

整體流程架構(gòu)圖,如下所示。

對(duì)應(yīng)的原理,在這里就不進(jìn)行贅述了,之前本人已經(jīng)有兩篇文章對(duì)層級(jí)式時(shí)間輪進(jìn)行了較為詳細(xì)的介紹了,有需要的小伙伴,可以直接去前幾篇文章去學(xué)習(xí),接下來(lái)我們進(jìn)行相關(guān)的實(shí)現(xiàn)。

時(shí)間輪數(shù)據(jù)模型

時(shí)間輪(TimingWheel)是一個(gè)存儲(chǔ)定時(shí)任務(wù)的環(huán)形隊(duì)列,數(shù)組中的每個(gè)元素可以存放一個(gè)定時(shí)任務(wù)列表,其中存放了真正的定時(shí)任務(wù),如下圖所示。

時(shí)間輪的最基本邏輯模型,由多個(gè)時(shí)間格組成,每個(gè)時(shí)間格代表當(dāng)前時(shí)間輪的基本時(shí)間跨度(tickMs),所以我們先來(lái)設(shè)計(jì)和定義開(kāi)發(fā)對(duì)應(yīng)的時(shí)間輪的輪盤模型。命名為Roulette類。

輪盤抽象類-Roulette

之所以定義這個(gè)抽象類

public abstract class Roulette {
	// 鏈表數(shù)據(jù)-主要用于存儲(chǔ)每個(gè)延時(shí)任務(wù)節(jié)點(diǎn)
    List<TimewheelTask> tasks = null;
    // 游標(biāo)指針?biāo)饕?    protected int index;
	// 時(shí)間輪輪盤的容量大小,如果是分鐘級(jí)別,一般就是60個(gè)格
    protected int capacity;
	// 時(shí)間輪輪盤的層級(jí),如果是一級(jí),它的上級(jí)就是二級(jí)
    protected Integer level;
    private AtomicInteger num = new AtomicInteger(0);

   // 構(gòu)造器
    public Roulette(int capacity, Integer level) {
        this.capacity = capacity;
        this.level = level;
        this.tasks = new ArrayList<>(capacity);
        this.index = 0;
    }
    // 獲取當(dāng)前下表的索引對(duì)應(yīng)的時(shí)間輪的任務(wù)
    public TimewheelTask getTask() {
        return tasks.get(index);
    }
   // init初始化操作機(jī)制
    public List<TimewheelTask> init() {
        long interval = MathTool.power((capacity + 1), level);
        long add = 0;
        TimewheelTask delayTask = null;
        for (int i = 0; i < capacity; i++) {
            add += interval;
            if (level == 0) {
                delayTask = new DefaultDelayTask(level);
            } else {
                delayTask = new SplitDelayTask(level);
            }
            //已經(jīng)轉(zhuǎn)換為最小的時(shí)間間隔
            delayTask.setDelay(add, TimeUnitProvider.getTimeUnit());
            tasks.add(delayTask);
        }
        return tasks;
    }

   // 索引下標(biāo)移動(dòng)
    public void indexAdd() {
        this.index++;
        if (this.index >= capacity) {
            this.index = 0;
        }
    }
   // 添加對(duì)應(yīng)的任務(wù)到對(duì)應(yīng)的隊(duì)列里面
    public void addTask(TimewheelTask task) {
        tasks.add(task);
    }
	// 給子類提供的方法進(jìn)行實(shí)現(xiàn)對(duì)應(yīng)的任務(wù)添加功能
    public abstract void addTask(int interval, MyTask task);
}
時(shí)間輪盤的熟悉信息介紹

鏈表數(shù)據(jù)-主要用于存儲(chǔ)每個(gè)延時(shí)任務(wù)節(jié)點(diǎn)。

List<TimewheelTask> tasks = null;

tasks也可以改成雙向鏈表 + 數(shù)組的結(jié)構(gòu):即節(jié)點(diǎn)存貯的對(duì)象中有指針,組成環(huán)形,可以通過(guò)數(shù)組的下標(biāo)靈活訪問(wèn)每個(gè)節(jié)點(diǎn),類似 LinkedHashMap。

游標(biāo)指針?biāo)饕?/p>

protected int index;

時(shí)間輪輪盤的容量大小,如果是分鐘級(jí)別,一般就是60個(gè)格

protected int capacity;

時(shí)間輪輪盤的層級(jí),如果是一級(jí),它的上級(jí)就是二級(jí)

protected Integer level;

init初始化時(shí)間輪輪盤對(duì)象模型,主要用于分配分配每一個(gè)輪盤上面元素的TimewheelTask,用于延時(shí)隊(duì)列的執(zhí)行任務(wù)線程,已經(jīng)分配對(duì)應(yīng)的每一個(gè)節(jié)點(diǎn)的延時(shí)時(shí)間節(jié)點(diǎn)數(shù)據(jù)。

 public List<TimewheelTask> init() {
	   //  那么整個(gè)時(shí)間輪的總體時(shí)間跨度(interval)
        long interval = MathTool.power((capacity + 1), level);
        long add = 0;
        TimewheelTask delayTask = null;
        for (int i = 0; i < capacity; i++) {
            add += interval;
            if (level == 0) {
                delayTask = new ExecuteTimewheelTask(level);
            } else {
                delayTask = new MoveTimewheelTask(level);
            }
            //已經(jīng)轉(zhuǎn)換為最小的時(shí)間間隔
            delayTask.setDelay(add, TimeUnitProvider.getTimeUnit());
            tasks.add(delayTask);
        }
        return tasks;
}
  • 整數(shù)a的n次冪:interval,計(jì)算跨度,主要是各級(jí)別之間屬于平方倍數(shù)

例如,第一層:20 ,第二層:20^2 ......

    //例如 n=7  二進(jìn)制 0   1                 1          1
    //a的n次冪 = a的2次冪×a的2次冪  ×   a的1次冪×a的1次冪  ×a
    public static long power(long a, int n) {
        int rtn = 1;
        while (n >= 1) {
            if((n & 1) == 1){
                rtn *= a;
            }
            a *= a;
            n = n >> 1;
        }
        return rtn;
    }
TimeUnitProvider工具類

主要用于計(jì)算時(shí)間單位操作的轉(zhuǎn)換

public class TimeUnitProvider {
    private static TimeUnit unit = TimeUnit.SECONDS;
    public static TimeUnit getTimeUnit() {
        return unit;
    }
}

代碼簡(jiǎn)介:

  • interval:代表著初始化的延時(shí)時(shí)間數(shù)據(jù)值,主要用于不同的層次的出發(fā)時(shí)間數(shù)據(jù)
  • for (int i = 0; i < capacity; i++) :代表著進(jìn)行for循環(huán)進(jìn)行添加對(duì)應(yīng)的延時(shí)隊(duì)列任務(wù)到集合中
  • add += interval,主要用于添加對(duì)應(yīng)的延時(shí)隊(duì)列的延時(shí)數(shù)據(jù)值!并且分配給當(dāng)前輪盤得到所有數(shù)據(jù)節(jié)點(diǎn)。

獲取當(dāng)前下標(biāo)的索引對(duì)應(yīng)的時(shí)間輪的任務(wù)節(jié)點(diǎn)

public TimewheelTask getTask() {
        return tasks.get(index);
}
層級(jí)時(shí)間輪的Bucket數(shù)據(jù)桶

在這里我們建立了一個(gè)TimewheelBucket類實(shí)現(xiàn)了Roulette輪盤模型,從而進(jìn)行建立對(duì)應(yīng)的我們的層級(jí)時(shí)間輪的數(shù)據(jù)模型,并且覆蓋了addTask方法。

public class TimewheelBucket extends Roulette {

    public TimewheelBucket(int capacity, Integer level) {
        super(capacity, level);
    }

    public synchronized void addTask(int interval, MyTask task) {
        interval -= 1;
        int curIndex = interval + this.index;
        if (curIndex >= capacity) {
            curIndex = curIndex - capacity;
        }
        tasks.get(curIndex).addTask(task);
    }
}

添加addTask方法,進(jìn)行獲取計(jì)算對(duì)應(yīng)的下標(biāo),并且此方法add操作才是對(duì)外開(kāi)發(fā)調(diào)用的,在這里,我們主要實(shí)現(xiàn)了根據(jù)層級(jí)計(jì)算出對(duì)應(yīng)的下標(biāo)進(jìn)行獲取對(duì)應(yīng)的任務(wù)執(zhí)行調(diào)度點(diǎn),將我們外界BizTask,真正的業(yè)務(wù)操作封裝到這個(gè)BizTask模型,交由我們的系統(tǒng)框架進(jìn)行執(zhí)行。

     public synchronized void addTask(int interval, BizTask task) {
        interval -= 1;
        int curIndex = interval + this.index;
        if (curIndex >= capacity) {
            curIndex = curIndex - capacity;
        }
        tasks.get(curIndex).addTask(task);
    }
時(shí)間輪輪盤上的任務(wù)點(diǎn)

我們針對(duì)于時(shí)間輪輪盤的任務(wù)點(diǎn)進(jìn)行設(shè)計(jì)和定義對(duì)應(yīng)的調(diào)度執(zhí)行任務(wù)模型。一個(gè)調(diào)度任務(wù)點(diǎn),可以幫到關(guān)系到多個(gè)BizTask,也就是用戶提交上來(lái)的業(yè)務(wù)任務(wù)線程對(duì)象,為了方便采用延時(shí)隊(duì)列的延時(shí)處理模式,再次實(shí)現(xiàn)了Delayed這個(gè)接口,對(duì)應(yīng)的實(shí)現(xiàn)代碼如下所示:

Delayed接口
public interface Delayed extends Comparable<Delayed> {
    /**
     * Returns the remaining delay associated with this object, in the
     * given time unit.
     *
     * @param unit the time unit
     * @return the remaining delay; zero or negative values indicate
     * that the delay has already elapsed
     */
    long getDelay(TimeUnit unit);
}
TimewheelTask時(shí)間輪刻度點(diǎn)
@Getter
public abstract class TimewheelTask implements Delayed {
    private List<BizTask> tasks = new ArrayList<BizTask>();
    private int level;
    private Long delay;
    private long calDelay;
    private TimeUnit calUnit;
    public TimewheelTask(int level) {
        this.level = level;
    }
    public void setDelay(Long delay, TimeUnit unit) {
        this.calDelay=delay;
        this.calUnit=unit;
    }
    public void calDelay() {
        this.delay = TimeUnit.NANOSECONDS.convert(this.calDelay, this.calUnit) + System.nanoTime(); 
    }
    public long getDelay(TimeUnit unit) {
        return this.delay - System.nanoTime();
    }
    public int compareTo(Delayed o) {
        long d = (getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS));
        return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
    }
    public void addTask(BizTask task) {
        synchronized (this) {
            tasks.add(task);
        }
    }
    public void clear() {
        tasks.clear();
    }
    public abstract void run();
}
  • 業(yè)務(wù)任務(wù)集合:private List<BizTask> tasks = new ArrayList<BizTask>();

    • 層級(jí)
    private int level;
    
    • 延時(shí)時(shí)間
      private Long delay;
    
    • 實(shí)際用于延時(shí)計(jì)算的時(shí)間,就是底層是統(tǒng)一化所有的延時(shí)時(shí)間到對(duì)應(yīng)的延時(shí)隊(duì)列
      private long calDelay;
      
    • 實(shí)際用于延時(shí)計(jì)算的時(shí)間,就是底層是統(tǒng)一化所有的延時(shí)時(shí)間到對(duì)應(yīng)的延時(shí)隊(duì)列(用于統(tǒng)一化的時(shí)間單位)
      private TimeUnit calUnit;
      
添加對(duì)應(yīng)的業(yè)務(wù)延時(shí)任務(wù)到輪盤刻度點(diǎn)
    public void addTask(BizTask task) {
        synchronized (this) {
            tasks.add(task);
        }
    }
刻度點(diǎn)的實(shí)現(xiàn)類

因?yàn)閷?duì)應(yīng)的任務(wù)可能會(huì)需要將下游的業(yè)務(wù)任務(wù)進(jìn)行升級(jí)或者降級(jí),所以我們會(huì)針對(duì)于執(zhí)行任務(wù)點(diǎn)分為,執(zhí)行任務(wù)刻度點(diǎn)和躍遷任務(wù)刻度點(diǎn)兩種類型。

  • 執(zhí)行任務(wù)延時(shí)隊(duì)列刻度點(diǎn)
public class ExecuteTimewheelTask extends TimewheelTask {
    public ExecuteTimewheelTask(int level) {
        super(level);
    }
    //到時(shí)間執(zhí)行所有的任務(wù)
    public void run() {
        List<BizTask> tasks = getTasks();
        if (CollectionUtils.isNotEmpty(tasks)) {
            tasks.forEach(task -> ThreadPool.submit(task));
        }
    }
}

再次我們就定義執(zhí)行這些任務(wù)的線程池為:

    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(20, 100, 3, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(10000),
            new MyThreadFactory("executor"), new ThreadPoolExecutor.CallerRunsPolicy());
  • 躍遷任務(wù)延時(shí)隊(duì)列刻度點(diǎn)
public class MoveTimewheelTask extends TimewheelTask {
    public MoveTimewheelTask(int level) {
        super(level);
    }
    //躍遷到其他輪盤,將對(duì)應(yīng)的任務(wù)
    public void run() {
        List<BizTask> tasks = getTasks();
        if (CollectionUtils.isNotEmpty(tasks)) {
            tasks.forEach(task -> {
                long delay = task.getDelay();
                TimerWheel.adddTask(task,delay, TimeUnitProvider.getTimeUnit());
            });
        }
    }
}

致辭整個(gè)時(shí)間輪輪盤的數(shù)據(jù)模型就定義的差不多了,接下來(lái)我們需要定義運(yùn)行在時(shí)間輪盤上面的任務(wù)模型,BizTask基礎(chǔ)模型。

BizTask基礎(chǔ)模型
public abstract class BizTask implements Runnable {
     protected long interval;
     protected int index;
     protected long executeTime;
     public BizTask(long interval, TimeUnit unit, int index) {
          this.interval  = interval;
          this.index = index;
          this.executeTime= TimeUnitProvider.getTimeUnit().convert(interval,unit)+TimeUnitProvider.getTimeUnit().convert(System.nanoTime(),TimeUnit.NANOSECONDS);
     }
     public long getDelay() {
          return this.executeTime - TimeUnitProvider.getTimeUnit().convert(System.nanoTime(), TimeUnit.NANOSECONDS);
     }
}

主要針對(duì)于任務(wù)執(zhí)行,需要交給線程池去執(zhí)行,故此,實(shí)現(xiàn)了Runnable接口。

  • protected long interval;:跨度操作
  • protected int index;:索引下表,在整個(gè)隊(duì)列里面的下表處理
  • protected long executeTime;:對(duì)應(yīng)的執(zhí)行時(shí)間

其中最重要的便是獲取延時(shí)時(shí)間的操作,主要提供給框架的Delayed接口進(jìn)行判斷是否到執(zhí)行時(shí)間了。

     public long getDelay() {
          return this.executeTime - TimeUnitProvider.getTimeUnit().convert(System.nanoTime(), TimeUnit.NANOSECONDS);
     }
層級(jí)時(shí)間輪的門面TimerWheel

最后我們要進(jìn)行定義和設(shè)計(jì)開(kāi)發(fā)對(duì)應(yīng)的整體的時(shí)間輪層級(jí)模型。

public class TimerWheel {

    private static Map<Integer, TimewheelBucket> cache = new ConcurrentHashMap<>();
    //一個(gè)輪表示三十秒
    private static int interval = 30;
    private static wheelThread wheelThread;

    public static void adddTask(BizTask task, Long time, TimeUnit unit) {
        if(task == null){
            return;
        }
        long intervalTime = TimeUnitProvider.getTimeUnit().convert(time, unit);
        if(intervalTime < 1){
            ThreadPool.submit(task);
            return;
        }
        Integer[] wheel = getWheel(intervalTime,interval);
        TimewheelBucket taskList = cache.get(wheel[0]);
        if (taskList != null) {
            taskList.addTask(wheel[1], task);
        } else {
            synchronized (cache) {
                if (cache.get(wheel[0]) == null) {
                    taskList = new TimewheelBucket(interval-1, wheel[0]);
                    wheelThread.add(taskList.init());
                    cache.putIfAbsent(wheel[0],taskList);
                }
            }
            taskList.addTask(wheel[1], task);
        }
    }
    static{
        interval = 30;
        wheelThread = new wheelThread();
        wheelThread.setDaemon(false);
        wheelThread.start();
    }
    private static Integer[] getWheel(long intervalTime,long baseInterval) {
        //轉(zhuǎn)換后的延時(shí)時(shí)間
        if (intervalTime < baseInterval) {
            return new Integer[]{0, Integer.valueOf(String.valueOf((intervalTime % 30)))};
        } else {
            return getWheel(intervalTime,baseInterval,baseInterval, 1);
        }
    }

    private static Integer[] getWheel(long intervalTime,long baseInterval,long interval, int p) {
         long nextInterval = baseInterval * interval;
        if (intervalTime < nextInterval) {
            return new Integer[]{p, Integer.valueOf(String.valueOf(intervalTime / interval))};
        } else {
            return getWheel(intervalTime,baseInterval,nextInterval, (p+1));
        }
    }

    static class wheelThread extends Thread {
        DelayQueue<TimewheelTask> queue = new DelayQueue<TimewheelTask>();

        public DelayQueue<TimewheelTask> getQueue() {
            return queue;
        }

        public void add(List<TimewheelTask> tasks) {
            if (CollectionUtils.isNotEmpty(tasks)) {
                tasks.forEach(task -> add(task));
            }
        }

        public void add(TimewheelTask task) {
            task.calDelay();
            queue.add(task);
        }

        @Override
        public void run() {
            while (true) {
                try {
                    TimewheelTask task = queue.take();
                    int p = task.getLevel();
                    long nextInterval = MathTool.power(interval, Integer.valueOf(String.valueOf(MathTool.power(2, p))));
                    TimewheelBucket timewheelBucket = cache.get(p);
                    synchronized (timewheelBucket) {
                        timewheelBucket.indexAdd();
                        task.run();
                        task.clear();
                    }
                    task.setDelay(nextInterval, TimeUnitProvider.getTimeUnit());
                    task.calDelay();
                    queue.add(task);
                } catch (InterruptedException e) {

                }
            }
        }
    }
}
TimerWheel的模型定義
private static Map<Integer, TimewheelBucket> cache = new ConcurrentHashMap<>();

一個(gè)輪表示30秒的整體跨度。

private static int interval = 30;

創(chuàng)建整體驅(qū)動(dòng)的執(zhí)行線程

private static wheelThread wheelThread;

 static{
        interval = 30;
        wheelThread = new wheelThread();
        wheelThread.setDaemon(false);
        wheelThread.start();
}

    static class wheelThread extends Thread {
        DelayQueue<TimewheelTask> queue = new DelayQueue<TimewheelTask>();
        public DelayQueue<TimewheelTask> getQueue() {
            return queue;
        }
        public void add(List<TimewheelTask> tasks) {
            if (CollectionUtils.isNotEmpty(tasks)) {
                tasks.forEach(task -> add(task));
            }
        }
        public void add(TimewheelTask task) {
            task.calDelay();
            queue.add(task);
        }
        @Override
        public void run() {
            while (true) {
                try {
                    TimewheelTask task = queue.take();
                    int p = task.getLevel();
                    long nextInterval = MathTool.power(interval, Integer.valueOf(String.valueOf(MathTool.power(2, p))));
                    TimewheelBucket timewheelBucket = cache.get(p);
                    synchronized (timewheelBucket) {
                        timewheelBucket.indexAdd();
                        task.run();
                        task.clear();
                    }
                    task.setDelay(nextInterval, TimeUnitProvider.getTimeUnit());
                    task.calDelay();
                    queue.add(task);
                } catch (InterruptedException e) {

                }
            }
   }

獲取對(duì)應(yīng)的時(shí)間輪輪盤模型體系
    private static Integer[] getWheel(long intervalTime,long baseInterval) {
        //轉(zhuǎn)換后的延時(shí)時(shí)間
        if (intervalTime < baseInterval) {
            return new Integer[]{0, Integer.valueOf(String.valueOf((intervalTime % 30)))};
        } else {
            return getWheel(intervalTime,baseInterval,baseInterval, 1);
        }
    }

    private static Integer[] getWheel(long intervalTime,long baseInterval,long interval, int p) {
         long nextInterval = baseInterval * interval;
        if (intervalTime < nextInterval) {
            return new Integer[]{p, Integer.valueOf(String.valueOf(intervalTime / interval))};
        } else {
            return getWheel(intervalTime,baseInterval,nextInterval, (p+1));
        }
    }

到這里相信大家,基本上應(yīng)該是了解了如何去實(shí)現(xiàn)對(duì)應(yīng)的時(shí)間輪盤的技術(shù)實(shí)現(xiàn)過(guò)程,有興趣希望整個(gè)完整源碼的,可以聯(lián)系我哦。謝謝大家!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-404562.html

到了這里,關(guān)于【算法數(shù)據(jù)結(jié)構(gòu)專題】「延時(shí)隊(duì)列算法」史上手把手教你針對(duì)層級(jí)時(shí)間輪(TimingWheel)實(shí)現(xiàn)延時(shí)隊(duì)列的開(kāi)發(fā)實(shí)戰(zhàn)落地(下)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 隊(duì)列——“數(shù)據(jù)結(jié)構(gòu)與算法”

    隊(duì)列——“數(shù)據(jù)結(jié)構(gòu)與算法”

    各位CSDN的uu們你們好呀,又好久不見(jiàn)啦,最近有點(diǎn)擺爛,甚是慚愧!?。?!今天,小雅蘭的內(nèi)容是隊(duì)列,下面,讓我們進(jìn)入隊(duì)列的世界吧!??! 隊(duì)列 隊(duì)列的概念及結(jié)構(gòu) 隊(duì)列:只允許在一端進(jìn)行插入數(shù)據(jù)操作,在另一端進(jìn)行刪除數(shù)據(jù)操作的特殊線性表,隊(duì)列具有先進(jìn)先出FIF

    2024年02月06日
    瀏覽(23)
  • 算法與數(shù)據(jù)結(jié)構(gòu)-隊(duì)列

    算法與數(shù)據(jù)結(jié)構(gòu)-隊(duì)列

    ??隊(duì)列跟棧一樣,也是一種操作受限的線性表數(shù)據(jù)結(jié)構(gòu)。不過(guò),隊(duì)列是先進(jìn)者先出。 ??棧只支持兩個(gè)基本操作:入棧 push()和出棧 pop()。隊(duì)列跟棧非常相似,支持的操作也很有限,最基本的操作也是兩個(gè):入隊(duì) enqueue(),放一個(gè)數(shù)據(jù)到隊(duì)列尾部;出隊(duì) dequeue(),從隊(duì)列頭部取

    2024年02月12日
    瀏覽(21)
  • 數(shù)據(jù)結(jié)構(gòu)與算法:隊(duì)列

    數(shù)據(jù)結(jié)構(gòu)與算法:隊(duì)列

    在上篇文章講解了棧之后,本篇也對(duì)這一章進(jìn)行收尾,來(lái)到隊(duì)列! 隊(duì)列(Queue)就像是排隊(duì)買票的人群。想象一下你去電影院看電影,人們?cè)谑燮贝翱谛纬梢粭l線(隊(duì)列)等待購(gòu)票。隊(duì)列遵循一個(gè)很重要的原則:先來(lái)先服務(wù)(First In, First Out,簡(jiǎn)稱FIFO)。這意味著最先到達(dá)并

    2024年02月22日
    瀏覽(26)
  • 【數(shù)據(jù)結(jié)構(gòu)和算法】--隊(duì)列

    【數(shù)據(jù)結(jié)構(gòu)和算法】--隊(duì)列

    隊(duì)列是只允許在一端進(jìn)行插入數(shù)據(jù)操作,在另一端進(jìn)行刪除數(shù)據(jù)操作的特殊線性表,隊(duì)列具有 先進(jìn)先出 FIFO(First In First Out) 的原則。 入隊(duì)列 :進(jìn)行 插入操作的一端稱為隊(duì)尾 。 出隊(duì)列 :進(jìn)行 刪除操作的一端稱為隊(duì)頭 。 隊(duì)列結(jié)構(gòu)聯(lián)想起來(lái)也非常簡(jiǎn)單,如其名,隊(duì)列就相當(dāng)于

    2024年02月05日
    瀏覽(27)
  • 數(shù)據(jù)結(jié)構(gòu)與算法04:隊(duì)列

    數(shù)據(jù)結(jié)構(gòu)與算法04:隊(duì)列

    目錄 什么是隊(duì)列? 循環(huán)隊(duì)列 雙端隊(duì)列 阻塞隊(duì)列 隊(duì)列的應(yīng)用場(chǎng)景 每日一練 在 上一篇文章 中講述了棧:先進(jìn)后出就是棧,隊(duì)列剛好相反, 先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)就是隊(duì)列 ,還是拿紙箱子來(lái)舉例:隊(duì)列可以理解為一個(gè)沒(méi)有底的紙箱子,往箱子里面放書(shū),一本一本疊上去,但是

    2024年02月06日
    瀏覽(27)
  • 算法與數(shù)據(jù)結(jié)構(gòu)(四)--隊(duì)列

    算法與數(shù)據(jù)結(jié)構(gòu)(四)--隊(duì)列

    隊(duì)列是另一種特殊的表,這種表只在表首(也稱為隊(duì)首)進(jìn)行刪除操作,只在表尾進(jìn)行插入操作。 隊(duì)列的修改是按 先進(jìn)先出 的規(guī)則進(jìn)行的,所以隊(duì)列又稱為先進(jìn)先出表,F(xiàn)irst In First Out,簡(jiǎn)稱FIFO表。映射到生活中就是排隊(duì)的隊(duì)伍。 如示意圖所示,a(1)就是隊(duì)首元素,a(n)就是隊(duì)

    2024年02月15日
    瀏覽(29)
  • Python數(shù)據(jù)結(jié)構(gòu)與算法-數(shù)據(jù)結(jié)構(gòu)(列表、棧、隊(duì)列、鏈表)

    Python數(shù)據(jù)結(jié)構(gòu)與算法-數(shù)據(jù)結(jié)構(gòu)(列表、棧、隊(duì)列、鏈表)

    數(shù)據(jù)結(jié)構(gòu)是指相互之間存在這一種或者多種關(guān)系的數(shù)據(jù)元素的集合和該集合中元素之間的關(guān)系組成。 簡(jiǎn)單來(lái)說(shuō),數(shù)據(jù)結(jié)構(gòu)就是設(shè)計(jì)數(shù)據(jù)以何種方式組織并存儲(chǔ)在計(jì)算機(jī)中。 比如:列表、集合與字典等都是一種數(shù)據(jù)結(jié)構(gòu)。 N.Wirth:“程序=數(shù)據(jù)結(jié)構(gòu)+算法” 數(shù)據(jù)結(jié)構(gòu)按照其 邏輯結(jié)

    2024年02月08日
    瀏覽(36)
  • 數(shù)據(jù)結(jié)構(gòu)之棧、隊(duì)列——算法與數(shù)據(jù)結(jié)構(gòu)入門筆記(四)

    數(shù)據(jù)結(jié)構(gòu)之棧、隊(duì)列——算法與數(shù)據(jù)結(jié)構(gòu)入門筆記(四)

    本文是算法與數(shù)據(jù)結(jié)構(gòu)的學(xué)習(xí)筆記第四篇,將持續(xù)更新,歡迎小伙伴們閱讀學(xué)習(xí) 。有不懂的或錯(cuò)誤的地方,歡迎交流 棧是一種線性數(shù)據(jù)結(jié)構(gòu),其 只允許在固定的一端進(jìn)行插入和刪除 元素操作。進(jìn)行數(shù)據(jù)插入和刪除操作的一端稱為棧頂 (Top), 另一端稱為棧底 (Bottom)。棧中的

    2024年02月08日
    瀏覽(23)
  • 數(shù)據(jù)結(jié)構(gòu)與算法:棧和隊(duì)列

    數(shù)據(jù)結(jié)構(gòu)與算法:棧和隊(duì)列

    棧是一種后入先出(LIFO)的線性邏輯存儲(chǔ)結(jié)構(gòu)。只允許在棧頂進(jìn)行進(jìn)出操作。 基本操作包括:入棧(push)/出棧(pop)/獲取棧頂元素(peek)。 棧的實(shí)現(xiàn)主要有兩種: 1. 數(shù)組實(shí)現(xiàn),即順序棧 2. 鏈表實(shí)現(xiàn),即鏈?zhǔn)綏?無(wú)論是以數(shù)組還是以鏈表實(shí)現(xiàn),入棧、出棧的時(shí)間復(fù)雜度都是

    2024年02月11日
    瀏覽(23)
  • 數(shù)據(jù)結(jié)構(gòu)與算法-雙端隊(duì)列

    Gitee上開(kāi)源的數(shù)據(jù)結(jié)構(gòu)與算法代碼庫(kù):數(shù)據(jù)結(jié)構(gòu)與算法Gitee代碼庫(kù) 雙端隊(duì)列、隊(duì)列、棧對(duì)比 定義 特點(diǎn) 隊(duì)列 一端刪除(頭)另一端添加(尾) First In First Out 棧 一端刪除和添加(頂) Last In First Out 雙端隊(duì)列 兩端都可以刪除、添加 優(yōu)先級(jí)隊(duì)列 優(yōu)先級(jí)高者先出隊(duì) 延時(shí)隊(duì)列 根據(jù)

    2024年02月13日
    瀏覽(21)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包