Netty03-核心组件NioEventLoopGroup解读

news2024/11/27 2:20:03

NioEventLoopGroup

在这里插入图片描述

可以看到NioEventLoopGroup继承了MultithreadEventExecutorGroup并且实现了EventLoopGroup接口,而这两个类被ExecutorService修饰,所以NioEventLoopGroup实际上是一个线程池,池中的对象其实就是单个的NioEventLoop。

源码解读

NioEventLoopGroup 的参数初始化

   // 进入无参构造
    public NioEventLoopGroup() {
        this(0);
    } 
public NioEventLoopGroup(int nThreads) {
    // group所包含的executor
        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());
    }
  protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }
    private static final int DEFAULT_EVENT_LOOP_THREADS;

    static {
        //默认线程数是cpu核数的两倍
        DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));

        if (logger.isDebugEnabled()) {
            logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
        }
    }
构造真正的NioEventGroup
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
        if (nThreads <= 0) {
            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
        }
        //1、
        //executor校验非空, 如果为空就创建ThreadPerTaskExecutor, 该类实现了 Executor接
        // 这个executor 是用来执行线程池中的所有的线程,也就是所有的NioEventLoop,其实从
        //NioEventLoop构造器中也可以知道,NioEventLoop构造器中都传入了executor这个参数。
        if (executor == null) {
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
      //2、
        //这里的children数组, 其实就是线程池的核心实现,线程池中就是通过指定的线程数组来实现       线程池;
        //数组中每个元素其实就是一个EventLoop,EventLoop是EventExecutor的子接口。

        children = new EventExecutor[nThreads];

        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                //3、
            //newChild(executor, args) 函数在NioEventLoopGroup类中实现了,
            // 实质就是就是存入了一个 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();
                    }
 						// 终止所有eventLoop上所执行的任务
                    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;
                        }
                    }
                }
            }
        }
//4、实例化线程工厂执行器选择器: 根据children获取选择器
        chooser = chooserFactory.newChooser(children);
 //5、为每个EventLoop线程添加 线程终止监听器
        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);
        }
//6、将children 添加到对应的set集合中去重, 表示只可读。
        Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
        Collections.addAll(childrenSet, children);
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }

children[i] = newChild(executor, args);

/**
 * newChild(executor, args) 里的方法
 * 我们可以看到 返回的就是一个 NioEventLoop
 */
@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
    return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
1. NioEventLoopGroup初始化时未指定线程数,那么会使用默认线程数,即 `线程数 = CPU核心数 * 2`;
2. 每个NioEventLoopGroup对象内部都有一组可执行的`NioEventLoop数组`,其大小是 nThreads, 这样就构成了一个线程池, `一个NIOEventLoop可以理解成就是一个线程`。
3. 所有的NIOEventLoop线程是使用相同的 executor、SelectorProvider、SelectStrategyFactory、RejectedExecutionHandler以及是属于某一个
    NIOEventLoopGroup的。这一点从 newChild(executor, args); 方法就可以看出:newChild()的实现是在NIOEventLoopGroup中实现的。
4. 当有IO事件来时,需要从线程池中选择一个线程出来执行,这时候的NioEventLoop选择策略是由GenericEventExecutorChooser实现的,并调用该类的next()方法。
5. 每个NioEventLoopGroup对象都有一个NioEventLoop选择器与之对应,其会根据NioEventLoop的个数,动态选择chooser(如果是2的幂次方,则按位运算,否则使用普通的轮询)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1296266.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图的邻接链表储存

喷了一节课 。。。。。。。、。 #include<stdio.h> #include<stdlib.h> #define MAXNUM 20 //每一个顶点的节点结构&#xff08;单链表&#xff09; typedef struct ANode{ int adjvex;//顶点指向的位置 struct ArcNode *next;//指向下一个顶点 …

持续集成交付CICD:使用Maven命令下载Nexus制品

目录 一、实验 1.Maven安装 2.Nexus搭建公共组仓库及Maven全局配置文件 3.使用Maven命令下载Nexus制品 一、实验 1.Maven安装 &#xff08;1&#xff09;CentOS环境安装步骤 tar -xf apache-maven-3.8.6-bin.tar.gz #解压 mv apache-maven-3.8.6 /usr/local/maven #移动…

Gateway和spring-boot-starter-web的恩怨情仇

为什么取这个题目&#xff0c;其实与我踩到的坑有关&#xff0c;说起来这个坑非常神奇&#xff0c;这里面就涉及到Gateway和spring-boot-starter-web底层所依赖的技术不兼容的问题。 一、背景 SpringCloud 版本 ---- Finchley.SR2 SpringBoot 版本 ---- 2.0.6.RELEASE 如果同…

非标设计之气缸的选型三

一、气缸正确安装方式&#xff0c;气缸调试注意事项 气缸安装方式&#xff1a; 气缸正确安装方式&#xff1a; NB(无支架) FB(脚座支架) FR(法兰) FA(前法兰) FB(后法兰) SC(单耳支架) DC(双耳支架) CT(耳轴支架) 气缸的安装形式决定方法&#xff1a;根据负荷运动方向决定气缸…

案例064:基于微信小程序的考研论坛设计

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

Navicat 技术指引 | 适用于 GaussDB 分布式的数据迁移工具

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

集简云 x 零售企业丨快速集成有赞商城和微盛企微管家,实现私域运营自动化

客户介绍 某公司是一家知名的饮料厂商&#xff0c;自1998年成立以来&#xff0c;一直致力于研发和生产各种热门饮品&#xff0c;如果汁、碳酸饮料、矿泉水等。因其独特的口感和健康的品质深受消费者的喜爱。企业拥有多个知名品牌&#xff0c;享有极高的品牌知名度和市场份额。该…

无人机自主巡检是什么?如何实现自动巡检?

近年来&#xff0c;随着科技不断演进&#xff0c;无人机自主巡检技术在多个领域取得显著进展。那么&#xff0c;无人机自主巡检到底是什么&#xff1f;它又是如何实现自动化的呢&#xff1f; 一、无人机自主巡检的定义 无人机自主巡检技术是利用无人机对目标对象或区域进行巡检…

初创公司和小型企业的渗透测试

在构建产品和推出多种产品时&#xff0c;安全性处于次要地位&#xff0c;特别是对于每个人都运行多个项目的引导式初创公司而言。 渗透测试的投资回报率不能直接计算&#xff0c;可以根据数据泄露的成本来计算。 由于高预算限制&#xff0c;初创公司领导者可能会放松安全措施…

Springboot+FastJson实现解析第三方http接口json数据为实体类(时间格式化转换、字段包含中文)

场景 若依前后端分离版手把手教你本地搭建环境并运行项目&#xff1a; 若依前后端分离版手把手教你本地搭建环境并运行项目_前后端分离项目本地运行-CSDN博客 在上面搭建SpringBoot项目的基础上&#xff0c;并且在项目中引入fastjson、hutool、lombok等所需依赖后。 系统需…

如何部署自己的服务渲染页面为Pdf文档

前言 相信大家都觉得官方发布的文档生成模块https://docs.mendix.com/appstore/modules/document-generation/很有用&#xff0c;它能把Mendix页面像素级导出到Pdf文件中&#xff0c;这对于归档等业务非常有价值。但部署依赖公有云提供的渲染服务&#xff0c;而中国本土用户对…

el-table 表格多选(后端接口搜索分页)实现已选中的记忆功能。实现表格数据和已选数据(前端分页)动态同步更新。

实现效果&#xff1a;&#xff08;可拉代码下来看&#xff1a;vue-demo: vueDemo&#xff09; 左侧表格为点击查询调用接口查询出来的数据&#xff0c;右侧表格为左侧表格所有选择的数据&#xff0c;由前端实现分页。 两个el-table勾选数据联动更新 实现逻辑&#xff1a; el-…

奇点云2023数智科技大会来了,“双12”直播见!

企业数字化进程深入的同时&#xff0c;也在越来越多的新问题中“越陷越深”&#xff1a; 数据暴涨&#xff0c;作业量和分析维度不同以往&#xff0c;即便加了机器&#xff0c;仍然一查就崩&#xff1b; 终于搞定新增渠道数据的OneID融合&#xff0c;又出现几个渠道要变更&…

华为配置Smart Link主备备份示例

定义 Smart Link&#xff0c;又叫做备份链路。一个Smart Link由两个接口组成&#xff0c;其中一个接口作为另一个的备份。Smart Link常用于双上行组网&#xff0c;提供可靠高效的备份和快速的切换机制。 Monitor Link是一种接口联动方案&#xff0c;它通过监控设备的上行接口…

Salesforce×阿里云,影响几何?

实际上&#xff0c;从这个视角来看&#xff0c;Salesforce和阿里云的合作也恰在成为着这个市场的一个新催化剂。“期待Salesforce能给中国市场带来一些新的增量&#xff0c;包括对合作伙伴的态度&#xff0c;对产品的态度等等。”一位CRM相关人士告诉我们。 那么&#xff0c;阿…

使用Pytorch实现Grad-CAM并绘制热力图

这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 看一下这个main cnn.py的文件 那这里我为了方便 就直接从官方的torch vision这个库当中导入一些我们常用的model 比如说我这里的例子是采用的mobile net v3 large这个模型 然后这里我将pretrain设…

考研真题数据结构

【2020年山西大学真题】用单链表保存m个整数&#xff0c;结点的结构为【data】[link]&#xff0c;且|data|≤n&#xff08;n为 正整数&#xff09;。现要求设计一个时间复杂度尽可能高效的算法&#xff0c;对于链表中data的绝对值相等的结点 &#xff0c;仅保留第一次出现的结…

Tair(2):Tair安装部署

1 安装相关依赖库 yum install -y gcc gcc-c make m4 libtool boost-devel zlib-devel openssl-devel libcurl-devel yum&#xff1a;是yellowdog updater modified 的缩写&#xff0c;Linux中的包管理工具gcc&#xff1a;一开始称为GNU C Compiler&#xff0c;也就是一个C编…

Kotlin(十五) 高阶函数详解

高阶函数的定义 高阶函数和Lambda的关系是密不可分的。在之前的文章中&#xff0c;我们熟悉了Lambda编程的基础知识&#xff0c;并且掌握了一些与集合相关的函数式API的用法&#xff0c;如map、filter函数等。另外&#xff0c;我们也了解了Kotlin的标准函数&#xff0c;如run、…

从零开始搭建链上dex自动化价差套利程序(13)

优化 优化触发条件&#xff1a; 之前的触发条件有问题&#xff0c;导致迟迟不能触发&#xff0c;优化后触发条件如下&#xff1a; dydx_take 0.0002apex_make 0.0005​float(b_first_price_apex)-float(s_first_price_dydx) > float(b_first_price_apex)*apex_makefloat…