Netty-時間輪

Netty-時間輪

歸檔

  • GitHub: Netty-時間輪

參考

  • Netty-時間輪

說明

  • 其實 Netty 框架并沒有使用,其可做學習算法原理的參考

單元測試

public class HashedWheelTimerTest2 {public static void main(String[] args) {System.out.println("---------> " + LocalTime.now());Timer timer = new HashedWheelTimer(); // sign_o_001Timeout timeout1 = timer.newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) {System.out.println("timeout1: " + LocalTime.now());}}, 10, TimeUnit.SECONDS);if (!timeout1.isExpired()) {timeout1.cancel(); // 取消任務}timer.newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) throws InterruptedException {System.out.println("timeout2: " + LocalTime.now());Thread.sleep(5000); // 占用 5 s,后面的任務會被延后}}, 1, TimeUnit.SECONDS);timer.newTimeout(new TimerTask() { // sign_c_001@Overridepublic void run(Timeout timeout) {System.out.println("timeout3: " + LocalTime.now());System.out.println(timeout.timer()); // 即:sign_o_001System.out.println(timeout.task().getClass()); // 即:sign_c_001}}, 3, TimeUnit.SECONDS);System.out.println("timer -> " + timer);System.out.println("---------> " + LocalTime.now());}
}

原理

類結構

  • io.netty.util.HashedWheelTimer
/*** 時間輪 */
public class HashedWheelTimer implements Timer {private final Worker worker = new Worker(); // 任務執行體private final Thread workerThread;          // 任務線程private final long tickDuration;            // 時針每次 tick 的時間,相當于時針間隔多久走到下一個 slotprivate final HashedWheelBucket[] wheel;    // 槽位數組private final Queue<HashedWheelTimeout> timeouts = PlatformDependent.newMpscQueue(); // MPSC 隊列,方便添加處理(用于削峰) sign_f_001private final Queue<HashedWheelTimeout> cancelledTimeouts = PlatformDependent.newMpscQueue(); // 記錄取消的,方便移除private final AtomicLong pendingTimeouts = new AtomicLong(0); // 記錄等待的任務數/** 槽位 */private static final class HashedWheelBucket {private HashedWheelTimeout head;    // 頭private HashedWheelTimeout tail;    // 尾}/** 任務封裝 */private static final class HashedWheelTimeout implements Timeout, Runnable {private final TimerTask task;   // 要執行的任務體private final long deadline;    // 終止時間戳long remainingRounds;           // 剩余輪數HashedWheelTimeout next;        // 與 prev 組成雙向鏈HashedWheelTimeout prev;}   
}

調用鏈

  • io.netty.util.HashedWheelTimer
/*** 時間輪 */
public class HashedWheelTimer implements Timer {/** 添加任務 */@Overridepublic Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {... // 省略校驗start(); // 啟動線程(如果還沒啟動的話)long deadline = System.nanoTime() + unit.toNanos(delay) - startTime; // 計算終止時間(startTime 一般為 1)... // 省略 deadline 溢值處理HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline);timeouts.add(timeout); // 添加到削峰隊列 sign_f_001return timeout;}
}
  • io.netty.util.HashedWheelTimer.Worker
    /** 任務執行體 */private final class Worker implements Runnable {private final Set<Timeout> unprocessedTimeouts = new HashSet<Timeout>(); // 方便 stop() 后記錄并返回private long tick; // 走時計數@Overridepublic void run() {... // 省略其他處理do {final long deadline = waitForNextTick();    // 計算并等待if (deadline > 0) {int idx = (int) (tick & mask);  // 計算要處理的槽位索引processCancelledTasks();        // 清空被取消的任務HashedWheelBucket bucket = wheel[idx];transferTimeoutsToBuckets();    // 將隊列中的任務轉移到相應的槽位里bucket.expireTimeouts(deadline);// 執行槽位里面的任務 sign_m_101tick++; // 計數加 1}} while (WORKER_STATE_UPDATER.get(HashedWheelTimer.this) == WORKER_STATE_STARTED); // ... // 省略 stop 處理}// 計算并等待private long waitForNextTick() {long deadline = tickDuration * (tick + 1);for (;;) {final long currentTime = System.nanoTime() - startTime;long sleepTimeMs = (deadline - currentTime + 999999) / 1000000;if (sleepTimeMs <= 0) { // 小于 0 表示不用等待if (currentTime == Long.MIN_VALUE) {return -Long.MAX_VALUE; // 返回最小值,表示后面的邏輯:任務都執行} else {return currentTime;     // 返回當前時間用于參考}}... // 省略 Windows 平臺處理try {Thread.sleep(sleepTimeMs);  // 線程睡眠} ... // catch 中斷異常處理}}// 轉移任務private void transferTimeoutsToBuckets() {for (int i = 0; i < 10_0000; i++) {HashedWheelTimeout timeout = timeouts.poll();... // 省略無新增的任務或任務被取消的處理long calculated = timeout.deadline / tickDuration;timeout.remainingRounds = (calculated - tick) / wheel.length; // 第幾輪數final long ticks = Math.max(calculated, tick);int stopIndex = (int) (ticks & mask); // 槽位索引HashedWheelBucket bucket = wheel[stopIndex];bucket.addTimeout(timeout);}}}
  • io.netty.util.HashedWheelTimer.HashedWheelBucket
    /** 槽位 */private static final class HashedWheelBucket {/** 執行任務 sign_m_101 */public void expireTimeouts(long deadline) {HashedWheelTimeout timeout = head;while (timeout != null) {HashedWheelTimeout next = timeout.next;if (timeout.remainingRounds <= 0) {     // 輪數為 0 或小于 0,才執行任務next = remove(timeout);if (timeout.deadline <= deadline) { // 小于當前時間(正常流程)timeout.expire();               // 執行任務 sign_m_201} ... // else 處理(狀態不對,拋異常),一般不會發生} else if (timeout.isCancelled()) {next = remove(timeout);} else {timeout.remainingRounds--;          // 減任務輪數}timeout = next;}}}
  • io.netty.util.HashedWheelTimer.HashedWheelTimeout
    /** 任務封裝 */private static final class HashedWheelTimeout implements Timeout, Runnable {/** 執行任務 sign_m_201 */public void expire() {if (!compareAndSetState(ST_INIT, ST_EXPIRED)) {return; // 可能已取消}try {timer.taskExecutor.execute(this); // 執行具體的任務} catch (Throwable t) {... // 任務執行異常,只作日志記錄(warn 級別)}}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/14233.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/14233.shtml
英文地址,請注明出處:http://en.pswp.cn/web/14233.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

多聯機分戶計費控制系統

中央空調多聯機分戶計費控制系統&#xff0c;針對國內常見幾種品牌的多聯機空調系統實行&#xff0c;遠程控制與計費管理。系統采用MQTT網絡協議&#xff0c;以訂閱/發布模式實行設備感知&#xff0c;實現對室外機、室內機的狀態監測、實時故障報警、累計分攤費用的實時數據傳導…

AI - 各類AI針對Excel分析對比

一個水果銷量表&#xff0c;Excel包含多個年份sheet&#xff0c;需要提取某個品種的水果每年的銷量&#xff0c;看看幾個AI的分析結果吧 1、文心一言3.5&#xff08;不支持Excel&#xff09; 不支持上傳Excel文件 2、 通義千問2.5&#xff08;完成★&#xff09; 順利完成…

C++-函數

函數&#xff08;Function&#xff09;&#xff1a;是一個提前封裝好的、可重復使用的、完成特定功能的獨立代碼單元。 特點&#xff1a;提前封裝、可重復使用的、完成特定功能 將針對特定功能的、有重復使用需求的代碼&#xff0c;提前封裝到函數內&#xff0c; 在需要的時候…

Linux(openEuler22.03) 定時備份任務 解決方案

目錄 定時備份與清理服務環境需求概述步驟詳解1. 配置 rsyncd 服務在 backup 服務器上配置 rsyncd 2. 在 nfs01 和 web01 上配置備份腳本腳本&#xff1a;backup_configs.sh配置定時任務 3. 在 backup 服務器上配置同步和清理腳本腳本&#xff1a;cleanup_backups.sh配置定時任…

游戲陪玩/在線租號/任務系統網站源碼

源碼介紹 游戲陪玩系統/在線租號系統/小姐姐陪玩任務系統/網游主播任務威客平臺源碼/絕地吃雞LOL在線下單/帶手機端/聲優線上游戲任務系統網站源碼 界面美觀,功能齊全,已對接支付,安裝教程放源碼壓縮包里了! 界面截圖 源碼下載 https://download.csdn.net/download/huayula…

【計算機網絡原理】淺談應用層協議的自定義和傳輸層UDP協議的總結

?????? write in front ??????? ?????????大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之處請多多諒解&#xff0c;讓我們一起共同進步????? . ?? ?xiaoxie?????????—CSDN博客 本文由xiaoxie????????? 原創 CSDN 如…

如何在cPanel面板中開啟雙因素身份驗證

本周有一個客戶&#xff0c;購買Hostease的主機&#xff0c; 客戶購買的是Linux虛擬主機&#xff0c;帶cPanel面板的。詢問我們的在線客服&#xff0c;如何加強他的cPanel的安全性。cPanel的雙因素身份驗證功能可以幫助幫客戶加固安全性。 雙因素身份驗證(2FA)是一種增強安全性…

【虛擬機軟件】 VMware Workstation Pro 17 新建 Linux 虛擬機教程(CentOS 7 版本)

文章目錄 下載安裝 VMware Workstation Pro 17 軟件下載 Linux 的 ISO 映像文件Linux版本選擇 新建虛擬機準備配置新建安裝 后續設置文章導航 我是一名立志把細節說清楚的博主&#xff0c;歡迎【關注】&#x1f389; ~ 原創不易&#xff0c; 如果有幫助 &#xff0c;記得【點贊…

slam14講(第8講、前端里程計)LK光流、直接法

直接法的引出 因為第7講大部分都是講特征點法&#xff0c;通過提取orb特征點和點的描述子&#xff0c;來構建兩幀圖像之間的特征點對應關系。這種方法會有缺點&#xff1a; 關鍵點和描述子提取計算耗時&#xff0c;如果相機的頻率高&#xff0c;則slam算法大部分耗時被占。特…

com.alibaba.fastjson.JSONObject循環給同一對象賦值會出現“$ref“:“$[0]“現象問題

1、問題描述 有些場景下&#xff0c;我們會選擇用JSONObject代替Map來處理業務邏輯&#xff0c;但是使用JSONObject時有一個需要注意的地方&#xff1a;在處理JSONObject對象時&#xff0c;引用的com.alibaba.fastjson.JSONObject&#xff0c;在一個集合中&#xff0c;循環給這…

【MySQL精通之路】InnoDB(10)-行格式

目錄 1.表數據結構 1.1 聚集索引數據結構 1.2 輔助索引數據結構 2.行格式 2.1 REDUNDANT行格式 2.2 REDUNDANT存儲特性 2.3 COMPACT行格式 2.4 COMPACT存儲特性 2.5 DYNAMIC行格式 2.6 DYNAMIC存儲特性 2.7 COMPRESSED行格式 2.8 COMPRESSED存儲特性 3.定義表格的…

數組-區間合并

一、題目描述 二、題目思路 這里提供滿足基本要求的解題思路&#xff1a; 1.先對列表內按照start大小升序排序&#xff0c;這里創建Comparator接口的實現類&#xff0c;重寫compare方法。 2.遍歷intervals&#xff0c;設置laststart、lastend兩個變量與當前區間相比較&#…

Ansible實戰YAML語言完成apache的部署,配置,啟動全過程

&#x1f3e1;作者主頁&#xff1a;點擊&#xff01; &#x1f3dd;?Ansible專欄&#xff1a;點擊&#xff01; ??創作時間&#xff1a;2024年5月24日15點59分 目錄 &#x1f4af;趣站推薦&#x1f4af; &#x1f38a;前言 ??YAML語言回顧 &#x1f386;1.編寫YAML文…

centos 安裝nginx 并配置https ssl

進入你要安裝的目錄 一般是/usr/local/ wget https://nginx.org/download/nginx-1.24.0.tar.gz解壓安裝包&#xff1a;使用以下命令解壓下載的Nginx安裝包&#xff1a; tar -zxvf nginx-1.24.0.tar.gz在編譯和安裝Nginx之前&#xff0c;確保您的系統上已安裝了必要的編譯工具和…

flume channel和interceptor簡介及官方用例

一、Flume Channels channel是在代理上暫存事件的存儲庫。Source 添加事件&#xff0c;Sink 將其刪除。 1、Memory Channel 事件存儲在具有可配置最大大小的內存中隊列中。它非常適合需要更高吞吐量的流&#xff0c;但在agent發生故障時會丟失暫存數據 Property Name Defau…

k近鄰和kd樹

K近鄰 選取k值的時候可以采用交叉驗證的方法 一般采用歐氏距離 kd樹 采用樹這個特殊的數據結構來實現k近鄰算法 先假設是二維的情況 下面講解kd樹的完整構造過程 找這個中位數是按照每棵子樹來創建的 前提是已經有了一棵kd樹,然后來一個實例點

java組合設計模式Composite Pattern

組合設計模式&#xff08;Composite Pattern&#xff09;是一種結構型設計模式&#xff0c;它允許你將對象組合成樹形結構來表示“部分-整體”的層次結構。組合模式使得客戶端對單個對象和組合對象的使用具有一致性。 // Component - 圖形接口 interface Graphic {void draw()…

Python UDP編程簡單實例

TCP是建立可靠的連接&#xff0c;并且通信雙方都可以以流的形式發送數據。 相對于TCP&#xff0c;UDP則是面向無連接的協議&#xff0c;不需要建立連接&#xff0c;只需要知道對方IP地址和端口號&#xff0c;就可以直接發送數據包。但是只管發送不保證到達。 雖然UDP傳輸數據…

Docker快速部署Seata的TC服務以及微服務引入Seata教程

目錄 一、使用docker部署Seata的TC服務 1、拉取TC服務鏡像 2、創建并運行容器 ?3、修改配置文件 4、在Nacos中添加TC服務的配置 5、重啟TC服務 二、微服務集成Seata 1、引入依賴 2、修改配置文件 Seata是阿里的一個開源的分布式事務解決方案&#xff0c;能夠為分布…

STM32學習和實踐筆記(31):輸入捕獲實驗

1.輸入捕獲介紹 在定時器中斷實驗章節中我們介紹了通用定時器具有多種功能&#xff0c;輸入捕獲就是其中一種。STM32F1除了基本定時器TIM6和TIM7&#xff0c;其他定時器都具有輸入捕獲功能。輸入捕獲可以對輸入的信號的上升沿&#xff0c;下降沿或者雙邊沿進行捕獲&#xff0c;…