• <menu id="sssag"></menu>
  • <menu id="sssag"></menu>
  • Fork me on GitHub

    netty系列之:EventLoop,EventLoopGroup和netty的默認實現

    簡介

    在netty中不管是服務器端的ServerBootstrap還是客戶端的Bootstrap,在創建的時候都需要在group方法中傳入一個EventLoopGroup參數,用來處理所有的ServerChannel和Channel中所有的IO操作和event。

    可能有的小伙伴還稍微看了一下netty的源碼,可能會發現還有一個和EventLoopGroup非常類似的類叫做EventLoop。那么EventLoopGroup和EventLoop有什么關系呢?他們的底層和channel的交互關系是怎么樣的呢?一起來看看吧。

    EventLoopGroup和EventLoop

    EventLoopGroup繼承自EventExecutorGroup:

    public interface EventLoopGroup extends EventExecutorGroup 
    

    在前面的文章中我們講過,EventExecutorGroup中有一個next方法可以返回對應的EventExecutor,這個方法在EventLoopGroup中進行了重寫:

        EventLoop next();
    

    next方法返回的不再是一個EventExecutor,而是一個EventLoop。

    事實上,EventLoop和EventLoopGroup的關系與EventExecutor和EventExecutorGroup的關系有些類似,EventLoop也是繼承自EventLoopGroup,EventLoopGroup是EventLoop的集合。

    public interface EventLoop extends OrderedEventExecutor, EventLoopGroup 
    

    在EventLoopGroup中,除了重寫的next方法之外,還添加了channel的注冊方法register,用于將channel和注冊到EventLoop中,從而實現channel和EventLoop的綁定。

    ChannelFuture register(Channel channel);
    

    在EventLoop中,自多添加了一個parent方法,用來表示EventLoop和EventLoopGroup的關聯關系:

    EventLoopGroup parent();
    

    EventLoopGroup在netty中的默認實現

    EventLoopGroup在netty中的默認實現叫做DefaultEventLoopGroup,先來看一下它的繼承關系:

    如果看了之前我講解的關于EventExecutorGroup的朋友可以看出來,DefaultEventLoopGroup和DefaultEventExecutorGroup的繼承關系是很類似的,DefaultEventLoopGroup繼承自MultithreadEventLoopGroup,而MultithreadEventLoopGroup又繼承自MultithreadEventExecutorGroup并且實現了EventLoopGroup接口:

    public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup 
    

    MultithreadEventLoopGroup是用多線程來處理Event Loop。

    在MultithreadEventLoopGroup中定義了一個DEFAULT_EVENT_LOOP_THREADS來存儲默認的處理Event Loop線程的個數:

    DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                    "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
    

    對于EventLoopGroup中新加的幾個register方法,MultithreadEventLoopGroup都是調用對應的next方法來實現的:

    public ChannelFuture register(Channel channel) {
            return next().register(channel);
        }
    

    這里的next()方法的實現實際上調用的是父類的next方法,也就是MultithreadEventExecutorGroup中的next方法,來選擇Group管理的一個EventLoop:

    public EventLoop next() {
            return (EventLoop) super.next();
        }
    

    對于DefaultEventLoopGroup來說,它繼承自MultithreadEventLoopGroup,實現了一個newChild方法,用來將傳入的executor封裝成為EventLoop:

        protected EventLoop newChild(Executor executor, Object... args) throws Exception {
            return new DefaultEventLoop(this, executor);
        }
    

    EventLoop在netty中的默認實現

    EventLoop在netty中的默認實現叫做DefaultEventLoop,先來看下它的繼承關系:

    DefaultEventLoop繼承自SingleThreadEventLoop,而SingleThreadEventLoop又繼承自SingleThreadEventExecutor并且實現了EventLoop接口。

    先來看下SingleThreadEventLoop的實現:

    public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop 
    

    SingleThreadEventLoop使用單一線程來執行提交的任務。它和SingleThreadEventExecutor相比有什么變化呢?

    首先 提供了一個tailTasks用來存儲pending的tasks:

    private final Queue<Runnable> tailTasks;
    

    這個tailTasks會被用在任務個數的判斷和操作上:

        final boolean removeAfterEventLoopIterationTask(Runnable task) {
            return tailTasks.remove(ObjectUtil.checkNotNull(task, "task"));
        }
    
        protected boolean hasTasks() {
            return super.hasTasks() || !tailTasks.isEmpty();
        }
    
        public int pendingTasks() {
            return super.pendingTasks() + tailTasks.size();
        }
    

    SingleThreadEventLoop中對register方法的實現最終調用的是注冊的channel中unsafe的register方法:

    channel.unsafe().register(this, promise);
    

    再來看一下DefaultEventLoop,DefaultEventLoop繼承自SingleThreadEventLoop:

    public class DefaultEventLoop extends SingleThreadEventLoop 
    

    除了構造函數之外,DefaultEventLoop實現了一個run方法,用來具體任務的執行邏輯:

        protected void run() {
            for (;;) {
                Runnable task = takeTask();
                if (task != null) {
                    task.run();
                    updateLastExecutionTime();
                }
    
                if (confirmShutdown()) {
                    break;
                }
            }
        }
    

    如果對比可以發現,DefaultEventLoop和DefaultEventExecutor中run方法的實現是一樣的。

    總結

    本文介紹了netty中EventLoop和EventLoopGroup的默認實現:DefaultEventLoop和DefaultEventLoopGroup,但是不知道小伙伴們有沒有發現,即使在最簡單的netty應用中也很少看到這兩個默認的EventLoop。最常用的反而是NioEventLoopGroup和NioEventLoop,這是因為DefaultEventLoop和DefaultEventLoopGroup只是使用了多線程技術,一個線程代表一個EventLoop,在EventLoop過多的情況下可能會造成線程和性能的浪費,所以在NioEventLoopGroup和NioEventLoop使用了NIO技術,通過使用channel、selector等NIO技術提升了EventLoop的效率。關于NioEventLoopGroup和NioEventLoop的詳細介紹,我們會在后一章中詳細講解,敬請期待。

    本文已收錄于 http://www.flydean.com/05-1-netty-eventloop-eventloopgroup/

    最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

    歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!

    posted @ 2022-03-07 21:17  flydean  閱讀(0)  評論(1編輯  收藏  舉報
    国产在线码观看超清无码视频,人妻精品动漫H无码,十大看黄台高清视频,国产在线无码视频一区二区三区,国产男女乱婬真视频免费,免费看女人的隐私超爽,狠狠色狠狠色综合久久蜜芽