Netty核心源码解析(三)--NioEventLoop

NioEventLoop介绍

NioEventLoop继承SingleThreadEventLoop,核心是一个单例线程池,可以理解为单线程,这也是Netty解决线程并发问题的最根本思路--同一个channel连接上的IO事件只由一个线程来处理,NioEventLoop中的单例线程池轮询事件队列,有新的IO事件或者用户提交的task时便执行对应的handler逻辑进行处理;

NioEventLoop循环执行三件事:

  1. 响应selector中的IO事件
  2. 检查任务队列中是否有用户提交的任务
  3. 检查定时任务是否到期,到期则移交至任务队列中

首先,一个NioEventLoop聚合一个selector对象,这个selector对象就是JDK NIO中的selector对象(Netty可以配置选择是否对JDK 中的selector优化,优化主要是对selectionkeys集合优化,后续详细解释),通过代码可以看到,NioEventLoop的构造器里完成了selector的创建----(具体的selector创建Netty通过继承了jdk的SelectorProvider来实现的)

 ,先看一下NioEventLoop的构造方法,NioEventLoop只提供了一个构造方法--

    NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler,EventLoopTaskQueueFactory queueFactory) {super(parent, executor, false, newTaskQueue(queueFactory), newTaskQueue(queueFactory),rejectedExecutionHandler);this.provider = ObjectUtil.checkNotNull(selectorProvider, "selectorProvider");this.selectStrategy = ObjectUtil.checkNotNull(strategy, "selectStrategy");final SelectorTuple selectorTuple = openSelector();this.selector = selectorTuple.selector;this.unwrappedSelector = selectorTuple.unwrappedSelector;}

构造函数中主要完成了selector的创建,选择器的实现策略,任务队列的创建,

先大概说一下run()方法的逻辑--

  1. 调用selector.select方法获取就绪IO事件的个数
  2. 判断是否有task---非定时任务
  3. 更新下一次定时任务的执行时间
  4. 处理selectedKeys---处理IO事件
  5. 执行任务---
    1. 获取到期的定时任务
    2. 根据配置控制任务异步任务执行时间
  6. 空轮训问题的处理

看一下具体实现--

首先获取IO就绪IO事件的个数

strategy = selectStrategy.calculateStrategy(selectNowSupplier, hasTasks());

calculateStrategy方法 --

  1. 如果当前有任务,则返回selectNow()方法的值---就绪的selected keys 个数
  2. 如果没有任务则返回-1;

然后看一下strategy为-1 的时候--

//返回-1的时候表示没有任务,此时计算
case SelectStrategy.SELECT:long curDeadlineNanos = nextScheduledTaskDeadlineNanos();if (curDeadlineNanos == -1L) {curDeadlineNanos = NONE; // nothing on the calendar}nextWakeupNanos.set(curDeadlineNanos);try {
//如果还是没有任务就需要重新计算一下就绪IO事件的个数,所以第一步在没有任务的时候直接将strategy赋值为-1是为了给处理定时任务留机会;if (!hasTasks()) {strategy = select(curDeadlineNanos);}} finally {//他的更新只是为了阻止不必要的选择器唤醒,所以lazySet的使用是可以的(没有比赛条件)nextWakeupNanos.lazySet(AWAKE);}

taskQueue中没有任务的时候获取定时任务中最近要生效的任务时间,然后再执行一次select方法;

之后根据ioRation(ioRation默认为50)来处理channel的IO事件和执行taskQueue中的任务;这里分三种情况:

  1. ioRation为100的时候,处理所有的IO事件并执行taskQueue中的所有任务;
     if (ioRatio == 100) {try {if (strategy > 0) {processSelectedKeys();}} finally {// Ensure we always run tasks.ranTasks = runAllTasks();}}
  2. ioRation小于100并且有就绪的IO事件的时候,先处理所有的就绪IO事件,然后以处理IO事件的时间作为基准分配异步任务的执行时间
    else if (strategy > 0) {final long ioStartTime = System.nanoTime();try {processSelectedKeys();} finally {// Ensure we always run tasks.final long ioTime = System.nanoTime() - ioStartTime;ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio);}}
  3. ioRation小于100且没有就绪IO事件的时候只执行一个异步任务
else {ranTasks = runAllTasks(0); // This will run the minimum number of tasks}

最后,判断是否发生了select是否发生了空轮训--
 

if (ranTasks || strategy > 0) {if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS && logger.isDebugEnabled()) {logger.debug("Selector.select() returned prematurely {} times in a row for Selector {}.",selectCnt - 1, selector);}selectCnt = 0;} else if (unexpectedSelectorWakeup(selectCnt)) { // Unexpected wakeup (unusual case)selectCnt = 0;}

至此,一次Eventloop循环就处理完了,总结一下---

  1. Eventloop是Netty运行的核心逻辑,主要处理三件事--IO读写事件,用户提交的异步任务,处理JDK中的空轮训问题;
  2. 核心逻辑体现在run()方法中;run()方法首先根据异步任务队列中是否有任务需要执行来决定是否需要处理定时任务;
  3. 如果有异步任务需要处理则同时获取就绪IO事件的个数;如果没有异步任务则计算定时任务的处理时间---处理完定时任务如果还是没有任务提交则轮询IO事件
  4. 根据配置控制时间执行IO事件和异步任务;

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

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

相关文章

2023谷歌开发者大会直播大纲「初稿」

听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 跨域学习者,从事过全栈研发、产品经理等工作,现任研发部门 CTO 。荣誉:2022年度博客之星Top4、博客专家认证、全栈领域优质创作者、新星计划导师,“星荐官共赢计…

【java】【idea2023版】Springboot模块没有.iml文件的问题

目录 方法一: 1、首先鼠标选中对应的对应的模块 ,按两下Ctrl键 2、project中选择对应的模块 3、运行mvn idea:module 命令​编辑 方法二: 1、可以右键点击open Terminal 2、然后在打开的Terminal里输入 方法一: 1、首先鼠…

【Rust】Rust学习 第十八章模式用来匹配值的结构

模式是 Rust 中特殊的语法,它用来匹配类型中的结构,无论类型是简单还是复杂。结合使用模式和 match 表达式以及其他结构可以提供更多对程序控制流的支配权。模式由如下一些内容组合而成: 字面值解构的数组、枚举、结构体或者元组变量通配符占…

leetcode做题笔记99. 恢复二叉搜索树

给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。 思路一:模拟题意 int midOrder(struct TreeNode **pre, struct TreeNode **err1, struct TreeNode **err2, struct TreeNo…

python VTK PyQt5 VTK环境搭建 创建 渲染窗口及三维模型,包含 三维模型交互;

目录 Part1. VTK 介绍 Part2. PyQt5 VTK环境搭建 安装Anaconda 自带Python Anaconda下载 安装PyQt5 安装 VTK Part3 :PyQt VTK 结合样例: Part1. VTK 介绍 VTK(visualization toolkit)是一个开源的免费软件系统,主要用于三维计算机图形…

C# 服务HTTPS 对 请求被中止: 未能创建 SSL/TLS 安全通道报错

1.如果windows支持HTTPS的TLS协议,则可以直接跳过 (Tls12) [WebMethod(Description "获取HttpsPost加密服务.")] public string HTTPSPOST(String input,String sUrl) { Log.Add("ReceiveNotice", &qu…

数字孪生赋能工业制造,为制造业带来新机遇与挑战

数字孪生技术是利用模拟仿真技术将实体对象数字化的技术。它基于虚拟现实、人工智能和云计算等技术,能够创建与真实物体相同的数字模型,并通过实时监测和分析手段,为制造企业提供关于该物体的全面数据,从而优化产品开发和生产过程…

Python如何操作网络爬虫

Python是一种非常强大的编程语言,用于网络爬虫操作也非常方便。Python提供了许多用于构建和操作网络爬虫的库和工具,如BeautifulSoup、Scrapy、Requests等。本文将详细介绍Python如何操作网络爬虫。 一、安装相关库 首先,我们需要安装Python…

几个nlp的小任务(序列标注)

几个nlp的小任务(序列标注) 安装一个 评估的库序列标注的介绍初始化参数加载数据集查看数据集编码选出示例展示数据预处理类,转token判断是否为 transformers.PreTrainedTokenizerFast类型继续分割word介绍对齐解决对齐对数据集进行批量预处理微调预处理模型设置 参数args使…

数据结构双向链表

Hello,好久不见,今天我们讲链表的双向链表,这是一个很厉害的链表,带头双向且循环,学了这个链表,你会发现顺序表的头插头删不再是一个麻烦问题,单链表的尾插尾删也变得简单起来了,那废…

jvm——内存模型

1.java内存模型 1.1 原子性 1.2 问题分析 这里与局部变量自增不同,局部变量调用iinc是在局部变量表槽位上进行自增。 静态变量是在操作数栈自增。 这里的主内存和工作内存时再JMM里的说法。 因为操作系统是时间片切换的多个线程轮流使用CPU. 1.3解决方法 JMM中…

【uniapp 监听键盘弹起与收回】

在uniapp中,可以通过使用小程序提供的API来监听键盘弹起与收回。 首先,在页面的onLoad函数中注册监听事件: onLoad() {uni.onKeyboardHeightChange(this.onKeyboardHeightChange); },然后,在页面的onUnload函数中取消注册监听事…

Kotlin 协程

Kotlin 协程(Coroutines)是一种轻量级的并发编程解决方案,旨在简化异步操作和多线程编程。它提供了一种顺序和非阻塞的方式来处理并发任务,使得代码可以更加简洁和易于理解。Kotlin 协程通过提供一套高级 API,使并发代…

C#矩阵XY排序

矩阵XY快速排序 using MyVision.Script.Method;public class MyScript : ScriptMethods {//struct MOTIONPOSXY_S{public double Pos_x;public double Pos_y;};//脚本执行该方法public bool Process(){//try{//脚本代码写在下方 List<double> PointX GetDoubleList(&qu…

Tensor-动手学深度学习-李沐_笔记

介绍 Tensor&#xff0c;又称"张量"&#xff0c;其实就是n维度数组。不同维度的Tensor示意图如下&#xff1a; 关于Tensor.reshape reshape函数可以处理总元素个数相同的任何新形状&#xff0c;【3&#xff0c;2&#xff0c;5】->【3&#xff0c;10】->【5&a…

GIT——.gitignore文件

git 提交时忽略的文件 HELP.md target/ .mvn/wrapper/maven-wrapper.jar **/src/main/**/target/ **/src/test/**/target/ logs/### STS ### .apt_generated .classpath .factorypath .project .settings .springBeans .sts4-cache### IntelliJ IDEA ### .idea *.iws *.iml *.i…

[系统] 电脑突然变卡 / 电脑突然** / 各种突发情况解决思路

今天来公司办公&#xff0c;开机之后发现电脑出现各种问题&#xff0c;死机、卡顿、点什么都加载&#xff0c;甚至开一个文件夹要1分钟才能打开&#xff0c;花了2个小时才解决&#xff0c;走了很多弯路&#xff0c;其实早点想通&#xff0c;5分钟就能解决问题&#xff0c;所以打…

本地部署 Stable Diffusion(Mac 系统)

在 Mac 系统本地部署 Stable Diffusion 与在 Windows 系统下本地部署的方法本质上是差不多的。 一、安装 Homebrew Homebrew 是一个流行的 macOS &#xff08;或 Linux&#xff09;软件包管理器&#xff0c;用于自动下载、编译和安装各种命令行工具和应用程序。有关说明请访问官…

ICT产教融合创新实训基地物联网实训室建设方案

一、概述 1.1物联网定义 物联网工程&#xff08;Internet of Things Engineering&#xff09;是一种以信息技术&#xff08;IT&#xff09;来改善实体世界中人们生活方式的新兴学科&#xff0c;它利用互联网技术为我们的日常生活活动提供服务和增益&#xff0c;从而让各种智能…

什么是Sui Kiosk,它可以做什么,如何赋能创作者?

创作者和IP持有者需要一些工具帮助他们在区块链上实现其商业模式。Sui Kiosk作为Sui上的一种原语可以满足这种需求&#xff0c;为创作者提供动态选项&#xff0c;使他们能够在任何交易场景中设置完成交易的条件。 本文将向您介绍为什么要在SuiFrens中使用Sui Kiosk&#xff0c…