Netty源码分析:1.2初始化NioEventLoop

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GG_and_DD/article/details/80416911

第一章节是主要是服务器启动的代码分析。章节目录有:
|———1.1初始化NioEventLoopGroup
|———1.2初始化NioEventLoop
|———1.3初始化NioServerSocketChannel
|———1.4服务器启动流程
为什么先从初始化开始了解服务器启动?
因为在我看服务器启动的相关源码的时候,有很多地方都是初始化的时候已经建立好的。所以我就从初始化的源码开始看起。这是我第一次看源码的笔记,仍有很多理解错误的地方和不解的地方。欢迎讨论。

本篇目录:

  • 继承类关系图
  • 初始化流程图
  • 代码分析
  • 疑问

继承类关系图

image.png

初始化流程图

image.png

1 NioEventLoop

  • 1 初始化父类SingleThreadEventLoop
  • 分析一下NioEventLoop构造的参数
    第一个参数NioEventLoopGroup parent :该NioEventLoop所在的线程池
    第二个参数Executor executorThreadPerTaskExecutor(newDefaultThreadFactory()) 的一个执行器。
    第三个参数SelectorProvider:主要是provider.openSelector()打开Selector。
    第四个参数SelectStrategy:一个选择策略,当线程进行事件循环的时候,就是根据该类来进行判断。
    第五个参数RejectedExecutionHandler:一个处理异常的类
    此时父类已经初始化完成,接下来是NioEventLoop类的一个初始化。
  • 2 获得一个SelectorTuple对象,该对象其实装着Selector。这一步就是通过selectorProvider获得Selector的
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
         //1
        super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
        if (selectorProvider == null) {
            throw new NullPointerException("selectorProvider");
        }
        if (strategy == null) {
            throw new NullPointerException("selectStrategy");
        }
        provider = selectorProvider; 
        final SelectorTuple selectorTuple = openSelector();//2
        selector = selectorTuple.selector;
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
    }

SingleThreadEventLoop

NioEventLoop 父类的SingleThreadEventLoop有参构造
有两个新参数
第一个int addTaskWakesUp: 默认值 false
第二个int maxPendingTasks: 默认值DEFAULT_MAX_PENDING_TASKS
- 1 对父类进行初始化
- 2 建立一个LinkedBlockingQueue的任务队列

protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                    boolean addTaskWakesUp, int maxPendingTasks,
                                    RejectedExecutionHandler rejectedExecutionHandler) {
         //1
        super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
        tailTasks = newTaskQueue(maxPendingTasks); //2
    }

SingleThreadEventExecutor

SingleThreadEventLoop 父类的SingleThreadEventLoop有参构造
- 1 是最终对父类AbstractEventExecutor的一个变量EventExecutorGroup 复制。
- 2 赋值给addTaskWakesUp ,当该线程有添加任务的时候就会改为ture,用来唤醒线程
- 3 赋值给maxPendingTasks,该线程最大允许任务数
- 4 建立一个任务队列

protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, int maxPendingTasks,
                                        RejectedExecutionHandler rejectedHandler) {

        super(parent);//1
        this.addTaskWakesUp = addTaskWakesUp;//2
        this.maxPendingTasks = Math.max(16, maxPendingTasks); //3
        this.executor = ObjectUtil.checkNotNull(executor, "executor"); 
        taskQueue = newTaskQueue(this.maxPendingTasks); //4
        rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    }

总结

NioEventLoop类实现的是单线程处理多个channel或者channel。那么它就应该是具有channel的一些信息以及与一条thread线程绑定在一起。如图:
image.png

疑问

  1. SingleThreadEventLoop 创建了一个tailTasks任务队列,在SingleThreadEventExecutor创建了一个taskQueue任务队列。他们分别有什么用?
    我也不太懂,应该是扩展设计吧。
  2. SingleThreadEventExecutor 有两个 Executor 和Thread 变量。分别代表什么意思?
    在4.0.x 版本,只有Thread 这个变量。在初始化的时候,SingleThreadEventExecutor有参构造会创建一个thread线程。并将这个线程赋予给Thread变量。
    而在4.1.x 版本。就有 Executor 和Thread 变量两个变量。在初始化的时候,是赋予 Executor 变量一个ThreadPertTaskExcutor对象。此时并没有用该Executor创建一个线程,thread也是空的。 直到调用 SingleThreadEventExecutor 的execute()方法 才会生成一个线程并赋值与Thread变量

猜你喜欢

转载自blog.csdn.net/GG_and_DD/article/details/80416911