Netty分布式pipeline管道Handler的刪除邏輯操作
上一小節(jié)我們學習了添加handler的邏輯操作, 這一小節(jié)我們學習刪除handler的相關邏輯
刪除handler操作
如果用戶在業(yè)務邏輯中進行ctx.pipeline().remove(this)這樣的寫法, 或者ch.pipeline().remove(new SimpleHandler())這樣的寫法, 則就是對handler進行刪除, 我們學習過添加handler的邏輯, 所以對handler刪除操作理解起來也會比較容易
我們首先跟到defaultChannelPipeline的remove(handler)的方法中:
public final ChannelPipeline remove(ChannelHandler handler) { remove(getContextOrDie(handler)); return this; }
方法體里有個remove()方法, 傳入一個 getContextOrDie(handler) 參數(shù), 這個 getContextOrDie(handler) , 其實就是根據(jù)handler拿到其包裝類HandlerContext對象
我們跟到getContextPrDie這個方法中
private AbstractChannelHandlerContext getContextOrDie(ChannelHandler handler) { AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(handler); //代碼省略 }
這里仍然會通過context(handler)方法去尋找, 再跟進去:
public final ChannelHandlerContext context(ChannelHandler handler) { if (handler == null) { throw new NullPointerException("handler"); } //從頭遍歷節(jié)點 AbstractChannelHandlerContext ctx = head.next; for (;;) { if (ctx == null) { return null; } //找到handler if (ctx.handler() == handler) { return ctx; } ctx = ctx.next; } }
這里我們看到尋找的方法也非常的簡單, 就是從頭結(jié)點開始遍歷, 遍歷到如果其包裝的handler對象是傳入的handler對象, 則返回找到的handlerContext
回到remove(handler)方法:
public final ChannelPipeline remove(ChannelHandler handler) { remove(getContextOrDie(handler)); return this; }
繼續(xù)跟到remove方法中:
private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) { //當前刪除的節(jié)點不能是head, 也不能是tail assert ctx != head && ctx != tail; synchronized (this) { //執(zhí)行刪除操作 remove0(ctx); if (!registered) { callHandlerCallbackLater(ctx, false); return ctx; } //回調(diào)刪除handler事件 EventExecutor executor = ctx.executor(); if (!executor.inEventLoop()) { executor.execute(new Runnable() { @Override public void run() { callHandlerRemoved0(ctx); } }); return ctx; } } callHandlerRemoved0(ctx); return ctx; }
首先要斷言刪除的節(jié)點不能是tail和head
然后通過remove0(ctx)進行實際的刪除操作, 跟到remove0(ctx)中:
private static void remove0(AbstractChannelHandlerContext ctx) { //當前節(jié)點的前置節(jié)點 AbstractChannelHandlerContext prev = ctx.prev; //當前節(jié)點的后置節(jié)點 AbstractChannelHandlerContext next = ctx.next; //前置節(jié)點的下一個節(jié)點設置為后置節(jié)點 prev.next = next; //后置節(jié)點的上一個節(jié)點設置為前置節(jié)點 next.prev = prev; }
這里的操作也非常簡單, 做了一個指針移動的操作, 熟悉雙向鏈表的小伙伴應該不會陌生, 刪除節(jié)點邏輯大概如下圖所示:
回到remove(ctx)方法
private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) { //當前刪除的節(jié)點不能是head, 也不能是tail assert ctx != head && ctx != tail; synchronized (this) { //執(zhí)行刪除操作 remove0(ctx); if (!registered) { callHandlerCallbackLater(ctx, false); return ctx; } //回調(diào)刪除handler事件 EventExecutor executor = ctx.executor(); if (!executor.inEventLoop()) { executor.execute(new Runnable() { @Override public void run() { callHandlerRemoved0(ctx); } }); return ctx; } } callHandlerRemoved0(ctx); return ctx; }
我們繼續(xù)往下看, 如果當前線程不是eventLoop線程則將回調(diào)刪除事件封裝成task放在taskQueue中讓eventLoop線程進行執(zhí)行, 否則, 則直接執(zhí)行回調(diào)刪除事件
跟到callHandlerRemoved0(ctx)方法中:
private void callHandlerRemoved0(final AbstractChannelHandlerContext ctx) { try { try { //調(diào)用handler的handlerRemoved方法 ctx.handler().handlerRemoved(ctx); } finally { //將當前節(jié)點狀態(tài)設置為已移除 ctx.setRemoved(); } } catch (Throwable t) { fireExceptionCaught(new ChannelPipelineException( ctx.handler().getClass().getName() + ".handlerRemoved() has thrown an exception.", t)); } }
與添加handler的邏輯一樣, 這里會調(diào)用當前handler的handlerRemoved方法, 如果用戶沒有重寫該方法, 則會調(diào)用其父類的方法, 方法體在ChannelHandlerAdapter類中有定義, 我們跟進去
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { }
同添加handler一樣, 也是一個空實現(xiàn), 這里用戶可以通過重寫來添加自己需要的邏輯
以上就是刪除handler的相關操作,更多關于Netty分布式pipeline管道刪除Handler的資料請關注腳本之家其它相關文章!
相關文章
springboot動態(tài)定時任務的實現(xiàn)方法示例
這篇文章主要給大家介紹了關于springboot動態(tài)定時任務的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-02-02