EventLoop 接口
EventLoop 的類層次結(jié)構(gòu)
在這個模型中,一個EventLoop 將由一個永遠都不會改變的Thread 驅(qū)動,同時任務(wù)(Runnable 或者Callable)可以直接提交給EventLoop 實現(xiàn),以立即執(zhí)行或者調(diào)度執(zhí)行。根據(jù)配置和可用核心的不同,可能會創(chuàng)建多個EventLoop 實例用以優(yōu)化資源的使用,并且單個EventLoop 可能會被指派用于服務(wù)多個Channel。
簡單理解:一個EventLoop相當(dāng)于一個循環(huán),并有一條線程管理(Thread),當(dāng)EventLoop添加或減少,線程也跟著改變.
-
Netty 4 中的I/O 和事件處理
所有的I/O操作和事件都由已經(jīng)被分配給了EventLoop的那個Thread來處理. -
Netty 3 中的I/O 操作
所有的出站(下游)事件都由調(diào)用線程處理,其可能是I/O 線程也可能是別的線程。
問題一:多個出站事件同意調(diào)用一個ChannelHandle,因此需要在ChannelHandler 中對出站事件進行仔細(xì)的同步.
問題二:當(dāng)Channel.write()方法導(dǎo)致異常時,需要生成并觸發(fā)一個exceptionCaught 事件。但是在Netty 3 的模型中,由于這是一個入站事件,需要在調(diào)用線程中執(zhí)行代碼,然后將事件移交給I/O 線程去執(zhí)行,然而這將帶來額外的上下文切換。
任務(wù)調(diào)度
- 使用EventLoop 調(diào)度任務(wù)
Channel ch = ...
ScheduledFuture<?> future = ch.eventLoop().schedule( // 調(diào)度任務(wù)在從現(xiàn)在開始的60 秒之后執(zhí)行
new Runnable() {
@Override
public void run() {
System.out.println("60 seconds later");
}
}, 60, TimeUnit.SECONDS);
實現(xiàn)細(xì)節(jié)
- 線程管理
EventLoop 的執(zhí)行邏輯
永遠不要將一個長時間運行的任務(wù)放入到執(zhí)行隊列中,因為它將阻塞需要在同一線程上執(zhí)行的任何其他任務(wù)。如果必須要進行阻塞調(diào)用或者執(zhí)行長時間運行的任務(wù),我們建議使用一個專門的EventExecutor。
理解:一般EventLoop利用inEventLoop(Thread)綁定一條線程,如果需要多線程處理,則使用EventExecutor.
-
EventLoop/線程的分配
1.異步傳輸
用于非阻塞傳輸(如NIO 和AIO)的EventLoop 分配方式
在當(dāng)前實現(xiàn)中,使用順序循環(huán)(round-robin)的方式進行分配以獲取一個均衡的分布,并且相同的EventLoop可能會被分配給多個Channel。
對于所有相關(guān)聯(lián)的Channel 來說,ThreadLocal 都將是一樣的。(同一個線程)
2.阻塞傳輸
阻塞傳輸(如OIO)的EventLoop 分配方式



