成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官:說說延遲任務(wù)的時(shí)間輪調(diào)度算法?

開發(fā) 架構(gòu)
Netty 框架是以性能著稱的框架,因此在它的框架中使用了大量提升性能的機(jī)制,例如 Netty 用于實(shí)現(xiàn)延遲隊(duì)列的時(shí)間輪調(diào)度算法就是一個(gè)典型的例子。使用時(shí)間輪算法可以實(shí)現(xiàn)海量任務(wù)新增和取消任務(wù)的時(shí)間度為 O(1),那么什么是時(shí)間輪調(diào)度算法呢?接下來我們一起來看。

本文繼續(xù)討論 Netty 相關(guān)的面試題,今天咱們來看一道 Netty 中的高頻面試題:說說 Netty 延遲任務(wù)的時(shí)間輪調(diào)度算法?

Netty 框架是以性能著稱的框架,因此在它的框架中使用了大量提升性能的機(jī)制,例如 Netty 用于實(shí)現(xiàn)延遲隊(duì)列的時(shí)間輪調(diào)度算法就是一個(gè)典型的例子。使用時(shí)間輪算法可以實(shí)現(xiàn)海量任務(wù)新增和取消任務(wù)的時(shí)間度為 O(1),那么什么是時(shí)間輪調(diào)度算法呢?接下來我們一起來看。

1.延遲任務(wù)實(shí)現(xiàn)

在 Netty 中,我們需要使用 HashedWheelTimer 類來實(shí)現(xiàn)延遲任務(wù),例如以下代碼:

public class DelayTaskExample {
    public static void main(String[] args) {
        System.out.println("程序啟動時(shí)間:" + LocalDateTime.now());
        NettyTask();
    }

    private static void NettyTask() {
        // 創(chuàng)建延遲任務(wù)實(shí)例
        HashedWheelTimer timer = new HashedWheelTimer(3, // 間隔時(shí)間
                TimeUnit.SECONDS, // 間隔時(shí)間單位
                100); // 時(shí)間輪中的槽數(shù)
        // 創(chuàng)建任務(wù)
        TimerTask task = new TimerTask() {
            @Override
            public void run(Timeout timeout) throws Exception {
                System.out.println("執(zhí)行任務(wù)時(shí)間:" + LocalDateTime.now());
            }
        };
        // 將任務(wù)添加到延遲隊(duì)列中
        timer.newTimeout(task, 0, TimeUnit.SECONDS);
    }
}

以上程序的執(zhí)行結(jié)果如下:

程序啟動時(shí)間:2024-06-04T10:16:23.033

執(zhí)行任務(wù)時(shí)間:2024-06-04T10:16:26.118

從上述執(zhí)行結(jié)果可以看出,我們使用 HashedWheelTimer 實(shí)現(xiàn)了延遲任務(wù)的執(zhí)行。

2.時(shí)間輪調(diào)度算法

那么問題來了,HashedWheelTimer 是如何實(shí)現(xiàn)延遲任務(wù)的?什么是時(shí)間輪調(diào)度算法?

查看 HashedWheelTimer 類的源碼會發(fā)現(xiàn),其實(shí)它是底層是通過時(shí)間輪調(diào)度算法來實(shí)現(xiàn)的,以下是 HashedWheelTimer 核心實(shí)現(xiàn)源碼(HashedWheelTimer 的創(chuàng)建源碼)如下:

private static HashedWheelBucket[] createWheel(int 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 int normalizeTicksPerWheel(int ticksPerWheel) {
    int normalizedTicksPerWheel = 1;
    while (normalizedTicksPerWheel < ticksPerWheel) {
        normalizedTicksPerWheel <<= 1;
    }
    return normalizedTicksPerWheel;
}
private static final class HashedWheelBucket {
    private HashedWheelTimeout head;
    private HashedWheelTimeout tail;
    // 省略其他代碼
}

在 HashedWheelTimer  中,使用了 HashedWheelBucket 數(shù)組實(shí)現(xiàn)時(shí)間輪的概念,每個(gè) HashedWheelBucket 表示時(shí)間輪中一個(gè) slot(時(shí)間槽),HashedWheelBucket 內(nèi)部是一個(gè)雙向鏈表結(jié)構(gòu),雙向鏈表的每個(gè)節(jié)點(diǎn)持有一個(gè) HashedWheelTimeout 對象,HashedWheelTimeout 代表一個(gè)定時(shí)任務(wù),每個(gè) HashedWheelBucket 都包含雙向鏈表 head 和 tail 兩個(gè) HashedWheelTimeout 節(jié)點(diǎn),這樣就可以實(shí)現(xiàn)不同方向進(jìn)行鏈表遍歷,如下圖所示:

時(shí)間輪算法的設(shè)計(jì)思想就來源于鐘表,如上圖所示,時(shí)間輪可以理解為一種環(huán)形結(jié)構(gòu),像鐘表一樣被分為多個(gè) slot 槽位。每個(gè) slot 代表一個(gè)時(shí)間段,每個(gè) slot 中可以存放多個(gè)任務(wù),使用的是鏈表結(jié)構(gòu)保存該時(shí)間段到期的所有任務(wù)。時(shí)間輪通過一個(gè)時(shí)針隨著時(shí)間一個(gè)個(gè) slot 轉(zhuǎn)動,并執(zhí)行 slot 中的所有到期任務(wù)。

任務(wù)的添加是根據(jù)任務(wù)的到期時(shí)間進(jìn)行取模,然后將任務(wù)分布到不同的 slot 中。如上圖所示,時(shí)間輪被劃分為 8 個(gè) slot,每個(gè) slot 代表 1s,當(dāng)前時(shí)針指向 2 時(shí),假如現(xiàn)在需要調(diào)度一個(gè) 3s 后執(zhí)行的任務(wù),應(yīng)該加入 2+3=5 的 slot 中;如果需要調(diào)度一個(gè) 12s 以后的任務(wù),需要等待時(shí)針完整走完一圈 round 零 4 個(gè) slot,需要放入第 (2+12)%8=6 個(gè) slot。

那么當(dāng)時(shí)針走到第 6 個(gè) slot 時(shí),怎么區(qū)分每個(gè)任務(wù)是否需要立即執(zhí)行,還是需要等待下一圈 round,甚至更久時(shí)間之后執(zhí)行呢?所以我們需要把 round 信息保存在任務(wù)中。例如圖中第 6 個(gè) slot 的鏈表中包含 3 個(gè)任務(wù),第一個(gè)任務(wù) round=0,需要立即執(zhí)行;第二個(gè)任務(wù) round=1,需要等待 1*8=8s 后執(zhí)行;第三個(gè)任務(wù) round=2,需要等待 2×8=8s 后執(zhí)行。所以當(dāng)時(shí)針轉(zhuǎn)動到對應(yīng) slot 時(shí),只執(zhí)行 round=0 的任務(wù),slot 中其余任務(wù)的 round 應(yīng)當(dāng)減 1,等待下一個(gè) round 之后執(zhí)行。

可以看出時(shí)間輪有點(diǎn)類似 HashMap,如果多個(gè)任務(wù)如果對應(yīng)同一個(gè) slot,處理沖突的方法采用的是拉鏈法。在任務(wù)數(shù)量比較多的場景下,適當(dāng)增加時(shí)間輪的 slot 數(shù)量,可以減少時(shí)針轉(zhuǎn)動時(shí)遍歷的任務(wù)個(gè)數(shù)。

時(shí)間輪定時(shí)器最大的優(yōu)勢就是,任務(wù)的新增和取消都是 O(1) 時(shí)間復(fù)雜度,而且只需要一個(gè)線程就可以驅(qū)動時(shí)間輪進(jìn)行工作。

責(zé)任編輯:姜華 來源: Java中文社群
相關(guān)推薦

2024-04-09 10:40:04

2024-10-22 16:39:07

2021-09-30 07:57:13

排序算法面試

2025-04-08 00:00:00

@AsyncSpring異步

2024-11-19 15:13:02

2023-12-27 18:16:39

MVCC隔離級別幻讀

2025-04-16 00:00:01

JWT客戶端存儲加密令

2024-03-05 10:33:39

AOPSpring編程

2024-08-22 10:39:50

@Async注解代理

2024-05-30 08:04:20

Netty核心組件架構(gòu)

2021-09-16 07:52:18

算法應(yīng)用場景

2024-02-20 08:13:35

類加載引用Class

2024-07-31 08:28:37

DMAIOMMap

2024-12-06 07:00:00

2024-03-14 14:56:22

反射Java數(shù)據(jù)庫連接

2021-11-25 10:18:42

RESTfulJava互聯(lián)網(wǎng)

2024-03-11 18:18:58

項(xiàng)目Spring線程池

2024-03-22 06:56:24

零拷貝技術(shù)數(shù)據(jù)傳輸數(shù)據(jù)拷貝

2020-07-02 07:52:11

RedisHash映射

2021-08-09 07:47:40

Git面試版本
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲欧美成人影院 | 久久r久久 | 亚洲一区免费 | 国产中文字幕在线 | 完全免费在线视频 | 亚洲精品乱码久久久久久久久 | 久久神马 | 亚洲精品免费看 | 国内精品视频在线 | 国产午夜精品一区二区三区嫩草 | 精品国产区 | 精品久久香蕉国产线看观看亚洲 | 欧州一区二区三区 | 国产午夜在线观看 | 中文字幕亚洲欧美 | 欧美黄在线观看 | aaa大片免费观看 | 国产激情片在线观看 | www.奇米| 无人区国产成人久久三区 | h片在线看| 福利视频一区二区三区 | wwwxxx日本在线观看 | 久久久久亚洲 | 国产成人综合久久 | 欧美视频三区 | 精品视频在线播放 | 日本不卡免费新一二三区 | 日韩精品1区2区3区 爱爱综合网 | 国产高潮好爽受不了了夜色 | 国产美女精品视频免费观看 | 污视频免费在线观看 | 国产免费观看一级国产 | 国产精品一区久久久 | 国产精品日韩一区 | 国产在线看片 | 欧美日韩精品一区二区 | 夜夜久久 | 精品一区二区三区四区视频 | 国产精品免费在线 | 国产盗摄视频 |