vlambda博客
学习文章列表

全网最通俗易懂的netty源码--EventLoopGroup的初始化

以EchoServer类为例,其通过下面这两行代码初始化了两个EventLoopGroup。

EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();

下面就来探究NioEventLoopGroup实例化背后的原理。查看其构造函数

NioEventLoopGroup

public NioEventLoopGroup() {
   this(0);
}

调用同类中的另一个构造函数

public NioEventLoopGroup(int nThreads{
    this(nThreads, (Executor) null);
}

继续调用下去

public NioEventLoopGroup(int nThreads, Executor executor) {
     this(nThreads, executor, SelectorProvider.provider());
}
public NioEventLoopGroup(
            int nThreads, Executor executor, final SelectorProvider selectorProvider)
 
{
   this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
}
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                             final SelectStrategyFactory selectStrategyFactory)
 
{
        super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}

到这里,调用父类的构造方法

MultithreadEventLoopGroup

protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
    super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}

进一步调用到父类

MultithreadEventExecutorGroup

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
     this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}

最终干活的构造函数

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                         EventExecutorChooserFactory chooserFactory, Object... args)
 
{
    if (nThreads <= 0) {
        throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
    }
    if (executor == null) {
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }
    //构造线程数组
    children = new EventExecutor[nThreads];
    //下面这个for循环将实例化children数组中的每一个元素
    for (int i = 0; i < nThreads; i ++) {
        boolean success = false;
        try {
            //实例化!!!!!!(准确的说不是创建线程,而是NioEventLoop,只是该对象关联了线程)
            children[i] = newChild(executor, args);
            success = true;
        } catch (Exception e) {

        } finally {

        }
    }

}

这个函数比较复杂,我们先不看这么多。其中,跟本节主题相关的就下面两行代码

//构造线程数组
children = new EventExecutor[nThreads];

这行代码主要就是为EventLoopGroup构造底层最重要的数据结构,线程数组。

//实例化!!!!!!(准确的说不是创建线程,而是NioEventLoop,只是该对象关联了线程)
children[i] = newChild(executor, args);

这一步是在循环中往上面的children数组中构建NioEventLoop对象。这个构造过程也比较复杂,我们以后会分析,现在记住这个结论就好了。
还需要注意的是,在构造函数的一路调用中,有下面几个参数需要注意

nThreads、executor、chooserFactory、selectorProvider、selectStrategyFactory、rejectedExecutionHandler

这几个参数很重要,后面会着重分析。文章的风格就是这样,先把握大局,以免掉入到各种复杂的细节中去挣扎很久还不知讲的啥。然后宏观的理清楚之后再一个个去分析里面的细节。
EventLoopGroup的初始化过程就讲完了,简单吧。