当前位置: 首页 > news >正文

Netty - NIO基础学习

一 简介

        1 三大模型是什么?

                IO三大模型之一,BIO,AIO,还有我们的主角NIO(non-blocking-io),也就是同步非阻塞式IO。这三种模型到底是干什么的?其实这三种模型都是对于JAVA的一种I/O框架,用来进行输入,输出操作。另一方面,以上三种模型提供的是统一的API操作,可以理解为JAVA针对于各种操作系统的IO模型进行的封装,从而具有一定的跨平台性等。作为开发者,我们不需要再了解有关操作系统层面的知识,直接使用这三种框架封装的API进行使用即可!

        2 NIO

                NIO(New Input/Output)是Java中的一种I/O(输入/输出)框架,主要用于处理异步I/O操作。它在Java 1.4版本中引入,旨在提高I/O操作的性能和可扩展性。

        NIO的主要特点:

  1. 非阻塞I/O:NIO允许线程在发起I/O操作后继续执行其他任务,而不必等待I/O操作完成,从而提高了应用的响应性。

  2. 选择器(Selector):NIO引入了选择器,允许单个线程管理多个通道(Channel),从而减少了资源消耗和上下文切换的开销。

  3. 通道(Channel):NIO使用通道进行数据的读写,通道是双向的,可以同时进行读和写操作。

  4. 缓冲区(Buffer):NIO使用缓冲区来存储数据,缓冲区在读写过程中充当数据的临时存储区。

  5. 文件通道(FileChannel):NIO还提供了文件通道,可以用于高效地处理文件I/O。

        NIO特别适合于需要处理大量并发连接的网络应用,如Web服务器和聊天应用等。通过非阻塞I/O和选择器,NIO能够更好地利用系统资源,提高整体性能。

二 NIO三大组件

        1.Channel(通道)

                相当于我们之前学习IO流操作中的输入输出流,起到一个通道的作用。但是在这里这个更加全面,既可以充当输入流,又可以充当输出流。是为双向通道。channel比Stream更底层,双向。

        2.Buffer(缓冲区)

                缓冲区,作为一个在网络或者是本地文件与计算机之间的桥梁,任何数据在进入通道Channel之前都需要经过Buffer。前者可以将数据读入Buffer,也可以将Buffer当中的数据写入Channel当中

        3.Selector(选择器)

                选择器是NIO中用于处理非阻塞I/O的核心组件。它允许单个线程管理多个通道。

                我认为将其与各种服务器设计模式相结合进行介绍,会更加清晰。

                我们以BIO(同步阻塞IO)举例,这样更加方便理解

                我们都知道,BIO是一种同步阻塞IO,在服务端与客户端之间,其会建立一个一个通道(Socket)以进行彼此之间的数据输入和输出,但是对于一个服务端,如果想要与多个客户端之间建立连接,那么就需要建立多个线程,也就是一个线程对应一个客户端。如下图:

                但是这样存在很大的弊端,如果有很多的客户端都进行访问,那么就会创建多个线程与其连接,就会导致CPU资源被占用许多,甚至直接宕机,导致客户端无法被外部访问。各个线程上下文之间的来回切换,线程创建,也会消耗大量资源。(这也就是为什么要创建线程池了。。。。)另一方面,BIO还有一个特点,那就是阻塞!如果一个客户端没有发送消息,那么对应的线程就会一直等待,直到客户端发送新的消息,才会继续进行执行。在此之前,等待的过程,就会造成CPU资源的大量占用。所以这种方式只适用于比较少的客户端访问。其实这就是服务器的设计之一 ----- 多线程设计模式

                有的大佬就会想到,可以创建线程池来处理问题,没错,我们上面面对的一个大问题就是:线程会随着客户端的访问而不断的创建。从而导致资源的大量占用。使用线程池可以设定线程的最大数量,用以解决客户端访问过多造成的问题。但是这种解决方式也存在很大问题,至于为什么,大家可以想一想。

                线程池设计模式。顾名思义,就是针对之前一个线程对应一个客户端的情形进行该进,变为一个线程针对多个客户端进行处理,如下:

            

                这种设计模式相比多线程有所提高,但是因为在阻塞模式下,依旧是一个线程在处理时仅仅只能够处理一个客户端,也就是Socket连接,因此其适合一个线程下连接的Scoket比较少的情况。

                Slector版设计模式。selector 的作用就是配合一个线程来管理多个 channel,获取这些 channel 上发生的事件,这些 channel 工作在非阻塞模式下不会让线程吊死在一个 channel 上。适合连接数特别多,但流量低的场景(low traffic),如下图:

              

                这种设计模式,一个线程对应一个选择器,这个选择器会直接监视其下的所有通道,一旦这些通道有什么动作发生,选择器就会将其汇报给线程,由线程进行解决。

                非阻塞的形式,也就是说,我们选择器监视下的各个通道,比如第一个通道,如果其当前没有任务,那么我们的选择器就不会等待,而是直接看下一个通道是否有任务。

                适合流量比较低,指的就是,如果我们的通道一下接收一个比较大的数据,那么选择器就会长时间的停留于它,直到它的任务结束,数据如果比较大,也就是如果流量比较大,那么就会影响其他通道的正常使用,因此适用于流量比较低的场景。

                由此可见,选择器适合于事件驱动的应用程序,可以有效地处理大量并发连接,减少线程上下文切换的开销。

三 Buffer - ByteBuffer

        上面我们简单说了几个比较缓冲区的Buffer,但是比较常用的实际上就一个ByteBuffer,所以我们拿这个作为详细介绍

        1.基本使用

@Slf4j
public class ChannelDemo1 {public static void main(String[] args) {try (RandomAccessFile file = new RandomAccessFile("helloword/data.txt", "rw")) {FileChannel channel = file.getChannel();ByteBuffer buffer = ByteBuffer.allocate(10);do {// 向 buffer 写入int len = channel.read(buffer);log.debug("读到字节数:{}", len);if (len == -1) {break;}// 切换 buffer 读模式buffer.flip();while(buffer.hasRemaining()) {log.debug("{}", (char)buffer.get());}// 切换 buffer 写模式buffer.clear();} while (true);} catch (IOException e) {e.printStackTrace();}}
}

                以上使用通道FileChannel与Buffer进行了一个简单的文件读取,以及对应文件内容的日志打印。

        2.BetyBuffer使用说明:

  1. 向 buffer 写入数据,例如调用 channel.read(buffer)

  2. 调用 flip() 切换至读模式

  3. 从 buffer 读取数据,例如调用 buffer.get()

  4. 调用 clear()compact() 切换至写模式

  5. 重复 1~4 步骤

        3.ByteBuffer结构

                其内部实际上是一个类似数组的存储结构,数组的长度也就是我们在使用allocate方法的时候自定义的。

                ByteBuffer主要有三个比较重要的属性:

                position(当前位置)

                limit(限制)

                capaciy(为数组容量)

                刚开始写入数据操作

                在我们刚开始进行数据写入操作的时候,position从头开始,后两个都在最后,每写入一个数据,对应的position指针就会向后移动一位,如图。

                

                获取数据

                使用filp获取数据的时候,对应的position指针就会从头开始,索引归零,取而代之的是limit,用来代替之前写入的数据的最大索引位置,为了防止读取出来的数据为空。

            

                 clear动作发生之后,会将数组内部的所有元素都清空,变为空,从头来过,重新进行写操作。

                

                还有一种写操作,为compact动作,比如我们因为某种原因,之前没有读取完的数据,那么就会直接将其进向前压缩,并且更新对应读取的时候的Position以及Limit的位置。从而达到写的操作。

相关文章:

Netty - NIO基础学习

一 简介 1 三大模型是什么? IO三大模型之一,BIO,AIO,还有我们的主角NIO(non-blocking-io),也就是同步非阻塞式IO。这三种模型到底是干什么的?其实这三种模型都是对于JAVA的一种I/O框架,用来进行…...

ArrayList的自动扩容机制源码

Java的ArrayList的自动扩容机制 ArrayList是 Java 中极为常用的动态数组实现类,它依托数组存储数据,能依据实际需求灵活变动容量,高效管理元素集合。在深挖底层源码细节前,先来了解创建ArrayList集合并添加元素时的运作流程&#…...

【llm_inference】react框架(最小code实现)

ReAct:结合推理和行动的大语言模型推理架构 GitHub Code: 人人都能看懂的最小实现 引言 在人工智能领域,大语言模型(LLM)的应用日益广泛,但如何让模型能够像人类一样,在思考的基础上采取行动&#xff0c…...

PT8M2103 触控 I/O 型 8-Bit MCU

1 产品概述 ● PT8M2103 是一款可多次编程(MTP)I/O 型8位 MCU,其包括 2K*16bit MTP ROM、256*8bit SRAM、PWM、Touch 等功能,具有高性能精简指令集、低工作电压、低功耗特性且完全集成触控按键功能。为各种触控按键的应用,提供了一种简单而又…...

英语时态学习+名词副词形容词变形方式

开发出头不容易 不如跨界卷英语 英语中的16种时态是由四种时间(现在、过去、将来、过去将来)和四种体(一般、进行、完成、完成进行)组合而成的。以下是每种时态的详细说明和例句: 一般现在时 (Simple Present) 用法…...

浏览器解析页面流程

从输入一个url到页面解析完成的流程 1. 网络进程 1. 获取url 浏览器首先判断输入的url是否有http缓存,如果有则直接从http缓存中读取数据并显示。如果没有,则进行下一步。进行DNS解析,获取域名对应的IP地址。 2.下载html文件 浏览器根据I…...

图的遍历之DFS邻接矩阵法

本题要求实现一个函数,对给定的用邻接矩阵存储的无向无权图,以及一个顶点的编号v,打印以v为起点的一个深度优先搜索序列。 当搜索路径不唯一时,总是选取编号较小的邻接点。 本题保证输入的数据(顶点数量、起点的编号等…...

Java --- JVM编译运行过程

目录 一.Java编译与执行流程: 二.编译过程: 1.编译器(javac): 2.字节码文件(.class): 三.执行过程: 1.启动JVM(Java虚拟机): 2…...

HTML5 拖拽 API 深度解析

一、HTML5 拖拽 API 深度解析 1.1 背景与发展 HTML5 的拖拽 API 是为了解决传统拖拽操作复杂而设计的。传统方法依赖鼠标事件和复杂的逻辑计算,而 HTML5 提供了标准化的拖拽事件和数据传递机制,使得开发者能够快速实现从一个元素拖拽到另一个元素的交互…...

GO--基于令牌桶和漏桶的限流策略

至于为什么要限流,字面意思已经很清楚了,就是为了减轻服务器的压力 下面我们将介绍两个限流策略----漏桶和令牌桶。 漏桶 原理介绍 漏桶,顾名思义就是一个漏斗,漏斗嘴的大小是固定的,所以不管漏斗现容量多大&#…...

MongoDB性能监控工具

mongostat mongostat是MongoDB自带的监控工具,其可以提供数据库节点或者整个集群当前的状态视图。该功能的设计非常类似于Linux系统中的vmstat命令,可以呈现出实时的状态变化。不同的是,mongostat所监视的对象是数据库进程。mongostat常用于…...

Axure设计之模拟地图人员移动轨迹

在产品原型设计时,为了更好的表达和呈现预期的效果,让客户或开发看一眼就能理解要实现的功能,往往需要在产品设计时尽量去接近现实,这就需要我们在使用Axure制作原型时应具有高度细节和逼真度的原型设计。原型设计不仅包含了产品的…...

Android环境搭建

Android环境搭建 第一步:安装 Homebrew 执行以下命令来安装 Homebrew: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"检测是否安装成功: brew --version第二步:安装 No…...

前端工程化面试题(一)

如何使用 Docker 部署前端项目? 使用 Docker 部署前端项目通常涉及以下几个步骤: 创建项目:首先,需要在本地创建并配置好前端项目。 准备 Docker 文件: .dockerignore:这个文件用于排除不需要上传到 Dock…...

模型案例:| 手机识别模型!

导读 2023年以ChatGPT为代表的大语言模型横空出世,它的出现标志着自然语言处理领域取得了重大突破。它在文本生成、对话系统和语言理解等方面展现出了强大的能力,为人工智能技术的发展开辟了新的可能性。同时,人工智能技术正在进入各种应用领…...

期权懂|个股期权交割操作流程是什么样的?

期权小懂每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 个股期权交割操作流程是什么样的? 一、行权申报: 期权买方在行权日通过其经纪商提交行权指令,表明其决定行使期权权利。 二、行权匹配&#xf…...

【openGauss】openGauss execute执行update语句,获取更新的行数

【openGauss】openGauss execute执行update语句,获取更新的行数 在openGauss中,可以使用execute语句执行update语句,并通过GET DIAGNOSTICS语句获取更新的行数。下面是一个示例: DO $$ DECLAREupdated_rows INTEGER; BEGINEXECUT…...

P8780 [蓝桥杯 2022 省 B] 刷题统计

题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 𝑎道题目,周六和周日每天做 𝑏 道题目。请你帮小明计算,按照计划他将在第几天实现做题数大于等于 𝑛 题? 输入格式 输入一行包含三…...

切比雪夫不等式:方差约束下的概率估计

切比雪夫不等式:方差约束下的概率估计 背景 在概率分析中,切比雪夫不等式是一个常用的工具,它通过引入随机变量的 方差信息,给出了偏离均值的概率界限。这一不等式是对 马尔科夫不等式 的自然扩展,结合了更丰富的分布…...

使用CancellationTokenSource来控制长时间sql查询中断

前端 <!-- 透明的覆盖层&#xff0c;显示在页面上方&#xff0c;包含进度条 --><Grid Visibility"{Binding IsLoading}" Background"Transparent" HorizontalAlignment"Stretch" VerticalAlignment"Stretch" ZIndex"1&…...

小红薯最新x-s 算法补环境教程12-06更新(下)

在上一篇文章中已经讲了如何去定位x-s生成的位置&#xff0c;本篇文章就直接开始撸代码吧 如果没看过的话可以看&#xff1a;小红薯最新x-s算法分析12-06&#xff08;x-s 56&#xff09;&#xff08;上&#xff09;-CSDN博客 1、获取加密块代码 首先来到参数生成的位置&…...

wazuh-modules-sca

wazuh中安全配置评估模块主线程执行wm_sca_main最后在wm_sca_start中循环执行&#xff0c;不会返回 // Module main function. It wont return #ifdef WIN32 DWORD WINAPI wm_sca_main(void *arg) {wm_sca_t *data (wm_sca_t *)arg; #else void * wm_sca_main(wm_sca_t * dat…...

Uniapp的App环境下使用Map获取缩放比例

概述 目前我试过的就是你用vue后缀是拿不到比例的你可以用nvue当然uniapp的uvue应该是更加可以的我使用的是高德所以你得在高德的后台声请原生的Android的key才可以如果是vue3的开发模式的话不用使用this来获取当前对象使用scale对象来接受和改变缩放比例会比较友好然后直接走…...

微信小程序配置less并使用

1.在VScode中下载Less插件 2.在微信小程序中依次点击如下按钮 选择 从已解压的扩展文件夹安装… 3.选中刚在vscode中下载安装的插件文件 如果没有修改过插件的安装目录&#xff0c;一般是在c盘下C:\用户\用户名.vscode\extensions\mrcrowl.easy-less-2.0.2 我的路径是&#xf…...

“全面支持公路数字化转型升级四大任务”视频孪生解决方案

数字经济的加速布局&#xff0c;对交通领域数字化转型、智能化升级提出明确要求。2024年上半年&#xff0c;为深入贯彻落实中共中央、国务院关于加快建设交通强国、数字中国等决策部署&#xff0c;推进公路水路交通基础设施数字转型、智能升级、融合创新&#xff0c;加快发展新…...

顶顶通电话机器人开发接口对接大语言模型之实时流TTS对接介绍

大语言模型一般都是流式返回文字&#xff0c;如果等全部文字返回了一次性去TTS&#xff0c;那么延迟会非常严重&#xff0c;常用的方法就是通过标点符号断句&#xff0c;返回了一句话就提交给TTS。随着流TTS的出现&#xff0c;就可以直接把大模型返回的文字灌给流TTS&#xff0…...

P3379 【模板】最近公共祖先(LCA)

【模板】最近公共祖先&#xff08;LCA&#xff09; https://www.luogu.com.cn/problem/P3379 题目描述 如题&#xff0c;给定一棵有根多叉树&#xff0c;请求出指定两个点直接最近的公共祖先。 输入格式 第一行包含三个正整数 N , M , S N,M,S N,M,S&#xff0c;分别表示…...

2030. gitLab A仓同步到B仓

文章目录 1 A 仓库备份 到 B 仓库2 B 仓库修改main分支的权限 1 A 仓库备份 到 B 仓库 #!/bin/bash# 定义变量 REPO_DIR"/home/xhome/opt/git_sync/zz_xx_xx" # 替换为你的本地库A的实际路径 REMOTE_ORIGIN"http://192.168.1.66:8181/zzkj_software/zz_xx_xx.…...

网易博客旧文-----如何在WINDOWS下载安卓(android)源代码并和eclipse做关联

如何在WINDOWS下载安卓&#xff08;android&#xff09;源代码并和eclipse做关联 2013-02-05 17:27:16| 分类&#xff1a; 安卓开发 | 标签&#xff1a; |举报 |字号大中小 订阅 编写安卓程序时&#xff0c;有时想看看安卓某些类的实现&#xff0c;但默认情况下环境是不带的。…...

MATLAB中axes函数用法

目录 语法 说明 示例 在图窗中定位多个坐标区 将坐标区设置为当前坐标区 在选项卡上创建坐标区 axes函数的功能是创建笛卡尔坐标区。 语法 axes axes(Name,Value) axes(parent,Name,Value) ax axes(___) axes(cax) 说明 axes 在当前图窗中创建默认的笛卡尔坐标区&…...