Netty原始碼解析 -- FastThreadLocal與HashedWheelTimer
阿新 • • 發佈:2021-01-17
Netty原始碼分析系列文章已接近尾聲,本文再來分析Netty中兩個常見元件:FastThreadLoca與HashedWheelTimer。
**原始碼分析基於Netty 4.1.52**
#### FastThreadLocal
FastThreadLocal比較簡單。
FastThreadLocal和FastThreadLocalThread是配套使用的。
FastThreadLocalThread繼承了Thread,FastThreadLocalThread#threadLocalMap 是一個InternalThreadLocalMap,該InternalThreadLocalMap物件只能用於當前執行緒。
InternalThreadLocalMap#indexedVariables是一個數組,存放了當前執行緒所有FastThreadLocal對應的值。
而每個FastThreadLocal都有一個index,用於定位InternalThreadLocalMap#indexedVariables。
![](https://upload-images.jianshu.io/upload_images/3804367-593366afa19959ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
FastThreadLocal#get
```
public final V get() {
// #1
InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
// #2
Object v = threadLocalMap.indexedVariable(index);
if (v != InternalThreadLocalMap.UNSET) {
return (V) v;
}
// #3
return initialize(threadLocalMap);
}
```
`#1` 獲取該執行緒的InternalThreadLocalMap
如果是FastThreadLocalThread,直接獲取FastThreadLocalThread#threadLocalMap。
否則,從UnpaddedInternalThreadLocalMap.slowThreadLocalMap獲取該執行緒InternalThreadLocalMap。
注意,UnpaddedInternalThreadLocalMap.slowThreadLocalMap是一個ThreadLocal,這裡實際回退到使用ThreadLocal了。
`#2` 每個FastThreadLocal都有一個index。
通過該index,獲取InternalThreadLocalMap#indexedVariables中存放的值
`#3` 找不到值,通過initialize方法構建新物件。
可以看到,FastThreadLocal中連hash演算法都不用,通過下標獲取對應的值,複雜度為log(1),自然很快啦。
#### HashedWheelTimer
HashedWheelTimer是Netty提供的時間輪排程器。
時間輪是一種充分利用執行緒資源進行批量化任務排程的排程模型,能夠高效的管理各種延時任務。
簡單說,就是將延時任務存放到一個環形佇列中,並通過執行執行緒定時執行該佇列的任務。
例如,
環形佇列上有60個格子,
執行執行緒每秒移動一個格子,則環形佇列每輪可存放1分鐘內的任務。
現在有兩個定時任務
task1,32秒後執行
task2,2分25秒後執行
而執行執行緒當前位於第6格子
則task1放到32+6=38格,輪數為0
task2放到25+6=31個,輪數為2
執行執行緒將執行當前格子輪數為0的任務,並將其他任務輪數減1。
![](https://upload-images.jianshu.io/upload_images/3804367-098c898caec34dcd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
缺點,時間輪排程器的時間精度不高。
因為時間輪演算法的精度取決於執行執行緒移動速度。
例如上面例子中執行執行緒每秒移動一個格子,則排程精度小於一秒的任務就無法準時呼叫。
HashedWheelTimer關鍵欄位
```
// 任務執行器,負責執行任務
Worker worker = new Worker();
// 任務執行執行緒
Thread workerThread;
// HashedWheelTimer狀態, 0 - init, 1 - started, 2 - shut down
int workerState;
// 時間輪佇列,使用陣列實現
HashedWheelBucket[] wheel;
// 暫存新增的任