Netty源码二:服务端创建NioEventLoopGroup

示例

还是拿之前启动源码的示例,来分析NioEventLoopGroup源码
image.png

NioEventLoopGroup构造函数

image.png
image.png
image.png
image.png
这里能看到会调到父类的MultiThread EventLoopGroup的构造方法

MultiThreadEventLoopGroup

image.png
这里我们能看到,如果传入的线程数目为0,那么就会设置2倍的核心的线程数目
接着,继续会调用父类的MultithreadEventExecutorGroup的构造方法

MultiThreadEventExecutorGroup

// todo 在这个构造方法中,完成了一些属性的赋值, 彻底构造完成  事件循环组对象
// todo  Object... args  是 selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject()的简写
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) {
   
        // todo 下面需要的参数,一开始使用无参的构造方法时, 传递进来的 就是null ,执行这一行代码, 创建默认的线程工厂
        // todo ThreadPerTaskExecutor  意味为当前的事件循环组   创建Executor , 用于 针对每一个任务的Executor   线程的执行器
        // todo  newDefaultThreadFactory根据它的特性,可以给线程加名字等,
        // todo 比传统的好处是 把创建线程和 定义线程需要做的任务分开, 我们只关心任务,  两者解耦
        // todo 每次执行任务都会创建一个线程实体
        // todo NioEventLoop 线程命名规则  nioEventLoop-1-XX    1代表是第几个group   XX第几个eventLoop
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }
    // todo children是线程执行器组里面的线程执行器
    children = new EventExecutor[nThreads];

    // todo  循环实例化
    for (int i = 0; i < nThreads; i++) {
   
        boolean success = false;
        try {
   
            // todo 创建EventLoop, 直接看一下这个newChild , 它的返回值是 EventExecutor , 但是如果我们直接去看它子类的实现的话
            // todo 会发现new 的实例其实的 NioEventLoop, 这并不奇怪, 因为,NioEventLoop间接实现了 EventExecutor 接口
            // todo 换句话说, 其实就是 NioEventLoop 就是 拥有线程执行器的功能
            children[i] = newChild(executor, args);
            success = true;
        } catch (Exception e) {
   
            // TODO: Think about if this is a good exception type
            throw new IllegalStateException("failed to create a child event loop", e);
        } finally {
   
            if (!success) {
   
                for (int j = 0; j < i; j++) {
   
                    children[j].shutdownGracefully();
                }

                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;
                    }
                }
            }
        }
    }
    // todo chooser 在这里 初始化了
    chooser = chooserFactory.newChooser(children);

    final FutureListener<Object> terminationListener = new FutureListener<Object>() {
   
        @Override
        public void operationComplete(Future<Object> future) throws Exception {
   
            if (terminatedChildren.incrementAndGet() == children.length) {
   
                terminationFuture.setSuccess(null);
            }
        }
    };

    for (EventExecutor e : children) {
   
        e.terminationFuture().addListener(terminationListener);
    }

    Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
    Collections.addAll(childrenSet, children);
    readonlyChildren = Collections.unmodifiableSet(childrenSet);
}

总结一下,这里一共做了几件事:

  1. 创建线程执行器:ThreadPerTaskExecutor
  2. 创建线程执行器里面的线程执行器:for {newChild}
  3. 创建线程选择器

用一张图总结一下:
image.png

这里的newChild比较重要,需要进一步分析, 父类的newChild最终会调用到子类 NioEventLoopGroup的newChild方法
image.png

NioEventLoopGroup

image.png
这里几个参数说明一下:

  1. 第一个是父类MutiThreadEventLoopGroup
  2. 第二个是父类创建的执行器ThreadPerTaskExecutor
  3. 第三个是SelectProvider:根据不同的系统来调用select
  4. 第四个是SelectStrategy
  5. 第五个是拒绝处理器

这里会调用到NioEventLoop的构造方法

NioEventLoop

image.png
后面就到了NioEventLoopGroup的创建流程了,这里就不详细debug了

相关推荐

  1. netty udp创建服务+客户

    2024-01-30 11:06:05       26 阅读
  2. netty创建tcp服务+客户

    2024-01-30 11:06:05       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-30 11:06:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-30 11:06:05       106 阅读
  3. 在Django里面运行非项目文件

    2024-01-30 11:06:05       87 阅读
  4. Python语言-面向对象

    2024-01-30 11:06:05       96 阅读

热门阅读

  1. go-zero 非k8s单体服务上线流程

    2024-01-30 11:06:05       55 阅读
  2. Debezium发布历史91

    2024-01-30 11:06:05       38 阅读
  3. 【计算机语言】浅谈 — 计算机语言分类

    2024-01-30 11:06:05       66 阅读
  4. 数论与图论

    2024-01-30 11:06:05       50 阅读
  5. STL:list实现

    2024-01-30 11:06:05       60 阅读
  6. http 状态码

    2024-01-30 11:06:05       49 阅读
  7. python的归并排序

    2024-01-30 11:06:05       58 阅读
  8. Filter过滤器学习使用

    2024-01-30 11:06:05       46 阅读
  9. 什么是IDE?新手用哪个IDE比较好?

    2024-01-30 11:06:05       65 阅读
  10. Debezium日常分享系列之:Debezium 2.6.0.Alpha1发布

    2024-01-30 11:06:05       58 阅读
  11. Python 和 LLM 的完美融合之路 (再谈 Function Impl)

    2024-01-30 11:06:05       46 阅读