從零開始學netty——為何重寫方法不一樣

abcjob發表於2021-09-09


相信大家看了decoder部分的時候肯定有點怪異,尤其是發現重寫的方法是channelRead0。方法上還帶了數字,完全不如channelRead好理解,下面的內容就是解答這個疑惑的。

繼承類的差異

第一個程式繼承的是ChannelInboundHandlerAdapter類,第二個程式是繼承的是SimpleChannelInboundHandler,SimpleChannelInboundHandler是有泛型引數的。可以指定一個具體的型別引數,透過decoder配合使用,非常方便。ChannelInboundHandlerAdapter則是直接操作byte陣列的。

類的關係
 ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler
 SimpleChannelInboundHandler extends ChannelInboundHandlerAdapter

上圖就是兩個類的宣告,SimpleChannelInboundHandler是繼承ChannelInboundHandlerAdapter的。也就是說SimpleChannelInboundHandler也擁有ChannelInboundHandlerAdapter的方法。

channelRead的重寫
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        boolean release = true;
        try {
            if (acceptInboundMessage(msg)) {//型別匹配
                I imsg = (I) msg;
                channelRead0(ctx, imsg);
            } else {
                release = false;
                ctx.fireChannelRead(msg);
            }
        } finally {
            if (autoRelease && release) {
                ReferenceCountUtil.release(msg);//釋放引用
            }
        }
    }

SimpleChannelInboundHandler的channelRead相比SimpleChannelInboundHandler而言,主要做了型別匹配以及用完之後釋放指向儲存該訊息的 ByteBuf 的記憶體引用。

ChannelInboundHandlerAdapter 的好處

相比之下,ChannelInboundHandlerAdapter 好像一無是處,畢竟他要自己處理資源的釋放,例如如下的呼叫

    buf.release();

如果說channelRead都是同步操作的話,SimpleChannelInboundHandler是不錯的選擇,如果操作是非同步的話,那他的邏輯就有點麻煩了,例如你把資料交給另外的執行緒處理了,還沒處理就會釋放了 。這裡必須說明一個問題,他的回收和jvm的垃圾回收還不完全是一回事。netty是自己做了引用計數的操作。

        buf.refCnt();

透過上面的api就可以獲取到計數的個數。具體的引用計數的部分,不知道也不影響netty的學習,這個點後面具體再說。ChannelInboundHandlerAdapter 處理自由的優點也就提現出來了,可以更好的處理更多的特定場景。

小總結

SimpleChannelInboundHandler的好處是可以處理不同的型別物件,並且可以做釋放。ChannelInboundHandlerAdapter 的好處則是更自由,在非同步的場景下更適合。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4798/viewspace-2800851/,如需轉載,請註明出處,否則將追究法律責任。

相關文章