前言
最近博主在研究螞蟻金服sofastack平台的sofa-jraft框架,其中涉及到選舉部分的定時任務實現HashedWheelTimer,拿出來單獨整理一下,其也是netty處理大量連接超時的心跳檢測實現。
算法描述
關於時間輪算法,有點類似於HashMap。在new 一個HashedWheelTimer實例的時候,可以傳入幾個參數。
第一,一個時間長度,這個時間長度跟具體任務何時執行沒有關系,但是跟執行精度有關。這個時間可以看作手表的指針循環一圈的長度。
然后第二,刻度數。這個可以看作手表的刻度。比如第一個參數為24小時,刻度數為12,那么每一個刻度表示2小時。時間精度只能到兩小時。時間長度/刻度數值越大,精度越大。=
然后添加一個任務的時候,根據hash算法得到hash值並對刻度數求模得到一個下標,這個下標就是刻度的位置。
然而有一些任務的執行周期超過了第一個參數,比如超過了24小時,就會得到一個圈數round。
簡點說,添加一個任務時會根據任務得到一個hash值,並根據時間輪長度和刻度得到一個商值round和模index,比如時間長度24小時,刻度為12,延遲時間為32小時,那么round=1,index=8。時間輪從開啟之時起每24/12個時間走一個指針,即index+1,第一圈round=0。當走到第7個指針時,此時index=7,此時剛才的任務並不能執行,因為剛才的任務round=1,必須要等到下一輪index=7的時候才能執行。
測試案例
/** * 每5秒執行一次 * @param args */ public static void main(String[] args) { final Timer timer = new HashedWheelTimer(Executors.defaultThreadFactory(),5,TimeUnit.SECONDS,2); TimerTask task = new TimerTask() { @Override public void run(Timeout timeout) throws Exception { System.out.println("task=========>>>>>>>>"); timer.newTimeout(this,5,TimeUnit.SECONDS); } }; timer.newTimeout(task,5,TimeUnit.SECONDS); }
參考
https://blog.csdn.net/nmgrd/article/details/77199666
https://www.cnblogs.com/eryuan/p/7955677.html