Netty原始碼分析(四):EventLoopGroup

貳級天災發表於2019-04-07

無論服務端或客戶端啟動時都用到了NioEventLoopGroup,從名字就可以看出來它是NioEventLoop的組合,是Netty多執行緒的基石。

類結構

Netty原始碼分析(四):EventLoopGroup
NioEventLoopGroup繼承自MultithreadEventLoopGroup,多提供了兩個方法setIoRatiorebuildSelectors,一個用於設定NioEventLoop用於IO處理的時間佔比,另一個是重新構建Selectors,來處理epoll空輪詢導致CPU100%的bug。這個兩個的用處在介紹NioEventLoop的時候在詳細介紹。其它的方法都在介面中有定義,先看下EventExecutorGroup

EventExecutorGroup

EventExecutorGroup繼承自ScheduledExecutorServiceIterable。這意味著EventExecutorGroup擁有定時處理任務的能力,同時本身可以迭代。它提供的方法有:

    /**
     * 是否所有事件執行器都處在關閉途中或關閉完成
     */
    boolean isShuttingDown();

    /**
     * 優雅關閉
     */
    Future<?> shutdownGracefully();

    Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit);

    /**
     * 返回執行緒池終止時的非同步結果
     */
    Future<?> terminationFuture();

    void shutdown();

    List<Runnable> shutdownNow();

    /**
     * 返回一個事件執行器
     */
    EventExecutor next();
複製程式碼

其中shutdownshutdownNow被標記為過時,不建議使用。EventExecutorGroup還重寫ScheduledExecutorService介面的方法,用於返回自定義的Future

EventLoopGroup

EventLoopGroup繼承自EventExecutorGroup,它和EventExecutorGroup想比多了註冊ChannelChannelPromise,同時重新next方法返回EventLoop

MultithreadEventExecutorGroup

建立NioEventLoopGroup時,最終都會呼叫MultithreadEventExecutorGroup的構造方法。

    protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        // 執行緒數必須大於0
        if (nThreads <= 0) {
            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
        }
        // 沒指定Executor就建立新的Executor
        if (executor == null) {
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
        // 建立EventExecutor陣列
        children = new EventExecutor[nThreads];
        for (int i = 0; i < nThreads; i++) {
            // 建立結果標識
            boolean success = false;
            try {
                // 建立EventExecutor物件
                children[i] = newChild(executor, args);
                // 設定建立成功
                success = true;
            } catch (Exception e) {
                throw new IllegalStateException("failed to create a child event loop", e);
            } finally {
                // 建立失敗,關閉所有已建立的EventExecutor
                if (!success) {
                    // 關閉所有已建立的EventExecutor
                    for (int j = 0; j < i; j++) {
                        children[j].shutdownGracefully();
                    }
                    // 確保所有已建立的EventExecutor已關閉
                    for (int j = 0; j < i; j++) {
                        EventExecutor e = children[j];
                        try {
                            while (!e.isTerminated()) {
                                e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
                            }
                        } catch (InterruptedException interrupted) {
                            // Let the caller handle the interruption.
                            Thread.currentThread().interrupt();
                            break;
                        }
                    }
                }
            }
        }
        // 建立EventExecutor選擇器
        chooser = chooserFactory.newChooser(children);
        // 建立監聽器,用於EventExecutor終止時的監聽
        final FutureListener<Object> terminationListener = new FutureListener<Object>() {
            @Override
            public void operationComplete(Future<Object> future) throws Exception {
                // 當EventExecutor全部關閉時
                if (terminatedChildren.incrementAndGet() == children.length) {
                    // 設定結果,並通知監聽器們。
                    terminationFuture.setSuccess(null);
                }
            }
        };
        // 給每個EventExecutor新增上監聽器
        for (EventExecutor e : children) {
            e.terminationFuture().addListener(terminationListener);
        }
        // 建立只讀的EventExecutor集合
        Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
        Collections.addAll(childrenSet, children);
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }
複製程式碼

整個構造方法做的就是EventExecutor的建立,包括建立的異常處理,成功通知等。 AbstractEventExecutorGroupMultithreadEventLoopGroupNioEventLoopGroup內部沒有特殊之處,就不擴充了。

文中帖的程式碼註釋全在:KAMIJYOUDOUMA, 有興趣的童鞋可以關注一下。


本篇到此結束,如果讀完覺得有收穫的話,歡迎點贊、關注、加公眾號【貳級天災】,查閱更多精彩歷史!!!

Netty原始碼分析(四):EventLoopGroup

相關文章