ChannelPipeline
單看名稱就能夠知道Channel
的管道。本篇將結合它的默認實現類DefaultChannelPipeline
來對它作一個簡單的介紹。git
ChannelPipeline
的事例圖。IO請求經由
ChannelOutboundHandler
中
ChannelOutboundHandler
處理以後寫出到服務端,服務接收到讀入後,由
ChannelInboundHandler
依次處理。 下面來看下
DefaultChannelPipeline
的類圖:
DefaultChannelPipeline
實現了
ChannelPipeline
接口,而
ChannelPipeline
又繼承了
ChannelInboundInvoker
、
ChannelOutboundInvoker
和
Iterable
。
ChannelInboundInvoker
:發起對
ChannelPipeline
中下一個
ChannelInboundHandler
的方法的調用。
ChannelOutboundInvoker
:發起對
ChannelPipeline
中下一個
ChannelOutboundHandler
的方法的調用。
Iterable
:可遍歷
ChannelPipeline
中的
ChannelHandler
。
NioEventLoop
繼承自
SingleThreadEventLoop
,而
SingleThreadEventLoop
又繼承自
SingleThreadEventExecutor
。
SingleThreadEventExecutor
內部持有一個Thread對象,是
Netty
多線程的基礎。 能夠認爲, 一個
NioEventLoop
與一個特定的線程進行了綁定,而且在其生命週期內,綁定的線程都不會再改變。
DefaultChannelPipeline
的主要工做就是對ChannelHandler
的管理,包括ChannelHandler
的增減,事件的觸發等。github
ChannelHandler
的增減以addFirst
方法爲例:bash
public final ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler) {
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
// 檢查handler是否能夠共享
checkMultiplicity(handler);
// 給AbstractChannelHandlerContext起個獨立的名字
name = filterName(name, handler);
// 建立DefaultChannelHandlerContext
newCtx = newContext(group, name, handler);
// 執行實際的添加操做
addFirst0(newCtx);
// channel還沒有註冊到eventloop
if (!registered) {
// 設置newCtx的狀態爲ADD_PENDING
newCtx.setAddPending();
// 設置過一會回調ChannelHandler的handlerAdded方法
callHandlerCallbackLater(newCtx, true);
return this;
}
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
newCtx.setAddPending();
executor.execute(new Runnable() {
@Override
public void run() {
callHandlerAdded0(newCtx);
}
});
return this;
}
}
callHandlerAdded0(newCtx);
return this;
}
複製代碼
addFirst
方法先檢查添加的ChannelHandler
是否能夠共享(判斷共享的方法是對於每一個channel當前ChannelHandler是否須要不一樣的狀態),再建立ChannelHandler
的上下文關係,使ChannelHandler
以鏈表方式存在於ChannelPipeline
中。當ChannelHandler
添加成功後,再調用ChannelHandler
的handlerAdded
方法。其它的添加方式和addFirst
相似。多線程
以fireChannelActive
方法爲例:ide
public final ChannelPipeline fireChannelActive() {
AbstractChannelHandlerContext.invokeChannelActive(head);
return this;
}
複製代碼
從HeadContext
的head開始,依次觸發下一個ChannelHandler
的channelActive
方法。oop
本篇簡單介紹了ChannelPipeline
的相關概念,當ChannelHandler
介紹完後,再具體介紹ChannelPipeline
中的HeadContext
和TailContext
。ui
文中帖的代碼註釋全在:KAMIJYOUDOUMA, 有興趣的童鞋能夠關注一下。this
本篇到此結束,若是讀完以爲有收穫的話,歡迎點贊、關注、加公衆號【貳級天災】,查閱更多精彩歷史!!! spa