Netty源码阅读- EchoServer流程-2.group的初始化

EchoServer流程-2.group的初始化

1.EventLoopGroup

在启动Netty的Server端时,先初始化了两个EventLoopGroup,分别为bossGroup和workerGroup:

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

io.netty.channel.EventLoopGroup是一个接口类型,继承了io.netty.concurrent.EventExecutorGroup(也是一个接口),EventExecutorGroup继承的接口已经不属于netty,属于原生的JDK的并发工具。
具体的实现类是NioEventLoopGroup
类图1

2.NioEventLoopGroup

如果使用无参数构造方法,在NioEventLoopGroup.java中,最终会使用到如下的构造方法:

/* NioEventLoopGroup.class */
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                             final SelectStrategyFactory selectStrategyFactory) {
        super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
    }

2.MultithreadEventLoopGroup

其中会自行生成线程数、执行器、Selector等参数(这个之后再分析),然后调MultithreadEventLoopGroup的构造方法(将线程数设置为物理核心数的二倍):

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

MultithreadEventExecutorGroup的构造方法。这个方法是最终进行了真正处理的方法,如下为重点逻辑:
执行器,属于JDK的并发

/* ThreadPerTaskExecutor.class */
// ThreadPerTaskExecutor是一个简单的线程
if (executor == null) {
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }

使用循环将children填补完全,并且处理失败

/* MultithreadEventLoopGroup.class */
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
    // create EventExecutor
    children[i] = newChild(executor, args)
    ......
}

3.NioEventLoopGroup

其中,newChild()方法的实现类为NioEventLoopGroup,但是在MultithreadEventLoopGroup中被定义为abstract方法。

/* NioEventLoopGroup.class */
@Override
    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        // 检查参数长度,使用工厂模式
        EventLoopTaskQueueFactory queueFactory = args.length == 4 ? (EventLoopTaskQueueFactory) args[3] : null;
        // 返回值的类型为NioEventLoop
        return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2], queueFactory);
    }

此处的NioEventLoop为新的类,查看继承关系图:

类图2

4.NioEventLoop

在NioEventLoop的构造方法中,可以追溯到AbstractEventExecutor的构造方法,AbstractEventExecutor记录了自己所属的EventExecutorGroup,并且在构造方法中填充:

/* AbstractEventExecutor.class */
protected AbstractEventExecutor(EventExecutorGroup parent) {
        this.parent = parent;
    }

之后的工作为SingleThreadEventExecutor的构造方法,其中SingleThreadEventExecutor需要更多的类成员。SingleThreadEventExecutor类中有很多负责各种执行和同步的类成员,这里不全部的详细说明。这里摘抄一段此构造方法的注释:

/**
     * Create a new instance
     *
     * @param parent            the {@link EventExecutorGroup} which is the parent of this instance and belongs to it
     * @param executor          the {@link Executor} which will be used for executing
     * @param addTaskWakesUp    {@code true} if and only if invocation of {@link #addTask(Runnable)} will wake up the
     *                          executor thread
     * @param maxPendingTasks   the maximum number of pending tasks before new tasks will be rejected.
     * @param rejectedHandler   the {@link RejectedExecutionHandler} to use.
     */

SingleThreadEventExecutor执行完毕后,SingleThreadEventLoop另外加入一个tailTasks,用于存储task。

super(parent, executor, addTaskWakesUp, taskQueue, rejectedExecutionHandler);
tailTasks = ObjectUtil.checkNotNull(tailTaskQueue, "tailTaskQueue");

此时,回到NioEventLoop的构造方法,完成selector的填充(selector作为java nio的核心概念,这里先不进行详细说明)。
到此,完成了一个EventExecutor的生成(实际上是生成了一个NioEventLoop实例)
chooser是一个用于实现选择策略的类,比如默认构造器DefaultEventExecutorChooserFactory实现了简单的RR(轮询),这个chooser的主要的作用是从EventExecutor中返回一个next()。在实现类中就是从children数组中挑一个成员出来。
遍历每一个children的元素,添加一个terminationListener,然后包装成一个不可修改的Set集合readonlyChildren。
到此,完成了NioEventLoopGroup的构造方法,EchoServer中的两个group初始化完毕。

5.总结

EventLoopGroup是netty中用来监听并处理Event的实体,可以理解为封装后的线程池。
EventLoopGroup的成员变量中,管理了许多EventLoop,它们是用来处理事件的,比如默认的
SingleThreadEventLoop一个真正处理事件的线程。
关于eventloop可以参考这篇文章:https://blog.csdn.net/thinking_fioa/article/details/81952066

图片数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值