IO多路复用
BIO(同步阻塞)
当客户端请求连接到服务端请求过程中其实是通过socket连接,socket的意思其实就是插座,可以理解成手机需要充电,这里的电要从服务端获取,手机的充电口和服务端的插座都是socket,假如客户端连接到服务端,但服务端从磁盘中查询数据的过程很慢,只要服务端没有查询完,这个客户端就要一直等着,如果有其他的客户端要来连接,也得等服务端把这个客户端的请求执行完了,才能再接受其他的客户端,而这个客户端有一个还好,有一万个怎么办呢?其他客户端只能干等着,这就是传统的BIO模式,也就是同步阻塞。
BIO的代码示例
public static void main(String[] args) throws IOException {// 创建一个 ServerSocket 对象,将其绑定到本地的 8888 端口,用于监听该端口的客户端连接请求ServerSocket serverSocket = new ServerSocket(8888);// 进入一个无限循环,使服务器可以持续接受客户端的连接请求while (true) {// 调用 ServerSocket 的 accept 方法,该方法会阻塞当前线程,直到有客户端连接到服务器// 一旦有客户端连接,该方法会返回一个 Socket 对象,用于与客户端进行通信Socket socket = serverSocket.accept();// 调用 Socket 对象的 getInputStream 方法,获取与客户端连接的输入流// 该输入流用于读取客户端发送的数据InputStream inputStream = socket.getInputStream();// 创建一个长度为 1024 的字节数组 buffer,用于存储从客户端读取的数据byte[] buffer = new byte[1024];// 定义一个整型变量 len,用于存储每次读取数据的长度int len;// 进入一个循环,不断从输入流中读取数据// inputStream.read(buffer) 会从输入流中读取数据到 buffer 数组中,并返回实际读取的字节数// 将读取的字节数赋值给 len,并判断是否大于 0// 如果大于 0,表示成功读取到数据,继续循环;否则,表示没有更多数据可读,退出循环while ((len = inputStream.read(buffer)) > 0) {// 将 buffer 数组中从索引 0 开始,长度为 len 的字节数据转换为字符串// 并将转换后的字符串打印到控制台,同时在前面加上提示信息“输入是:”System.out.println("输入是:" + new String(buffer, 0, len));}}}
BIO代码中如果获取流和读取流执行很慢的话,整个期间服务端是没有办法处理其他客户端请求。
NIO(同步非阻塞)
可以一个线程处理多个Socket连接。具体分为以下几个步骤
当客户端连接服务端时会存在一个通道,这个通道就叫SocketChannel,服务端会有一个轮询器,(下文把客户端的SocketChannel简称为channel),channel会被注册到这个轮询器上,如果有其他的的客户端来连接的话,也会把相应的channle注册到轮询器上。
这个轮询器会有一个线程,里面一直不断的轮询,不断地查询这些通道的状态,看看有没有可连接的状态,不断地循环查找,当找到一个是连接状态的了,就把这个是连接状态的通道拿出来,改成监听是否可读状态,再注册到轮询器上,注册后继续轮询找,当找到一个是可读状态的channel那么就可以直接读取数据了,这样其他的客户端就不需要像BIO那样,需要等之前的客户端请求完全执行完了才能轮到自己,只要哪个客户端的事件状态有变化了,就会被循环查找到执行对应的操作了。
但是在这个不断查找通道的循环中,这些通道的状态都是在Kernel内核中,也就是说循环中的每一次查找都要从用户空间切换到内核空间,然后才能查找到状态,这样效率非常低。所以就要把查询状态的这些通道的fd文件描述符传给内核,这时遍历的行为就变成内核自己来做了,循环查找这些通道的状态,然后把这些状态结果从内核空间切换到用户空间,然后再返回给轮询器。整个过程中,只有传入时用户空间切换到内核空间,以及返回时从内核空间切换到用户空间这个过程了。
而这一次调用可以查询到多个路通道的状态,也就是说这些路通道被一次调用给复用了,这就是多路复用
轮询器
select和poll是轮询器的两种实现,select在把fd文件描述符传递给内核时,数量是有限制的,也就是不能一次把所有的都传递到内核中去遍历,而poll没有数量限制,可以一次性都传递。现在确实让内核来遍历这些通道的状态了。
但是内核还是得遍历嘛效率还是不够高,我们思考是否可以把循环去掉,等哪个通道可以连接了、可读了就直接能找到呢?这就是epoll。
epoll
epoll一开始是创建好ServerSocket,然后绑定好端口号进行监听,这三个行为select和poll都有。下面就是epoll特有的行为了,首先是先调用内核的epoll_create调用后会在内核开启两个空间,一个是红黑树,另一个是双向链表,接着再调用内核的epoll_ctl,会将要监听的fd文件描述符放到红黑树空间里,并标注要监听的是可连接事件,然后再调用内核的epoll_wait,他就会遍历这个双向链表来拿东西,拿的就是已经是可连接状态的fd。
但是双向了链表是什么时候有东西的呢?这里涉及到另一个技术“中断”,比如当网卡接收到数据时,内核就会检测到网络套接字的状态变化,此时网络设备驱动程序会通过内核将数据放入到对应的fd中的接收缓冲区,并修改相应的文件描述符状态,接着内核就会检查红黑树中注册的文件描述符,发现对应的fd现在是可连接的。
接着内核会将该fd给插入到双向列表中,表示这个文件描述符已经准备好被处理了。这样调用epoll_wait时就能从双向链表中拿到了,此时就不需要在内核中遍历了,效率大大提高。
NIO代码示例
public static void main(String[] args) throws IOException {// 打开一个 Selector,用于监控多个通道上的 I/O 事件Selector selector = Selector.open();// 打开一个 ServerSocketChannel,用于接收客户端连接ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();// 将 ServerSocketChannel 绑定到本机 localhost 的 8080 端口serverSocketChannel.socket().bind(new InetSocketAddress("localhost", 8080));// 设置 ServerSocketChannel 为非阻塞模式serverSocketChannel.configureBlocking(false);// 将 ServerSocketChannel 注册到 Selector,并关注 ACCEPT(接收连接)事件serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// 无限循环,等待 I/O 事件的发生while (true) {// 阻塞等待至少一个注册事件发生selector.select();// 获取所有触发的事件集合Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();// 遍历所有事件while (iterator.hasNext()) {SelectionKey key = iterator.next();// 处理完一个事件后,从集合中移除,防止重复处理iterator.remove();// 如果该事件是连接接收事件if (key.isAcceptable()) {// 接收客户端连接,返回一个 SocketChannelSocketChannel socketChannel = serverSocketChannel.accept();// 设置接收到的 SocketChannel 为非阻塞模式socketChannel.configureBlocking(false);// 将该 SocketChannel 注册到 Selector,并关注 READ(读取数据)事件socketChannel.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) { // 如果该事件是数据可读事件// 获取触发该事件的 SocketChannelSocketChannel socketChannel = (SocketChannel) key.channel();// 创建一个 ByteBuffer 用于存放读取的数据ByteBuffer buffer = ByteBuffer.allocate(1024);// 从 SocketChannel 中读取数据到 ByteBuffer 中socketChannel.read(buffer);// 输出读取到的数据System.out.println("数据:" + new String(buffer.array()));// 关闭该 SocketChannelsocketChannel.close();}}}
}
AIO
当在NIO中获取到可读的事件或者可写的事件后,依然还是要靠程序自己来执行后续的操作,这个还要靠程序自己来去执行后续的操作的。这个还要靠自己去主动做的特点就是同步的意思。
那么如果是在AIO的情况下,获取到可读或可写的事件后,内核主动去做,不需要程序主动了,这就是异步
相关文章:
IO多路复用
BIO(同步阻塞) 当客户端请求连接到服务端请求过程中其实是通过socket连接,socket的意思其实就是插座,可以理解成手机需要充电,这里的电要从服务端获取,手机的充电口和服务端的插座都是socket,假…...
AF3 OpenFoldSingleDataset类解读
AlphaFold3 data_modules 模块的 OpenFoldSingleDataset类 是 OpenFold 中的一个数据集类,继承自 torch.utils.data.Dataset,用于加载和处理蛋白质结构数据,以支持 AlphaFold3 相关的深度学习任务。OpenFoldSingleDataset 读取的多序列比对(MSA)数据、模板(template)特征…...
高级java每日一道面试题-2025年3月21日-微服务篇[Nacos篇]-什么是Nacos?
如果有遗漏,评论区告诉我进行补充 面试官: 什么是Nacos? 我回答: Nacos综合解析 一、Nacos的定义与功能 Nacos是阿里巴巴开源的一个专注于动态服务发现、配置管理和服务管理平台,其名称来源于Dynamic Naming and Configuration Service(…...
C++练习3
练习 终端上输出 3.14 要求实现 myDouble的 operator operator- operator* (不考虑进位) class myOut { 没有私有成员 只有公开函数 } myOut out; out << 1 终端输出1 out << 3.14 终端输出3.14 out << "hello" 终…...
Deepseek API+Python 测试用例一键生成与导出 V1.0.6(加入分块策略,返回更完整可靠)
随着Deepseek APIPython 测试用例一键生成与导出 V1.0.5的试用不断深入,在处理需求文档内容时,会出现由于文档内容过长导致大模型返回的用例远达不到我们的期望数量;另一方面,是接口文档的读取,如果接口数量过多&#…...
JDK 17 + Spring Boot 3 全栈升级实战指南--从语法革新到云原生,解锁企业级开发新范式
🚀 技术升级背景 随着 JDK 17(LTS) 与 Spring Boot 3 的发布,Java 生态迎来性能与开发效率的双重飞跃。相较于 JDK 8,JDK 17 在语法、API、GC 等方面均有显著优化,而 Spring Boot 3 则全面拥抱 Jakarta EE…...
phpStorm2021.3.3在windows系统上配置Xdebug调试
开始 首先根据PHP的版本下载并安装对应的Xdebug扩展在phpStorm工具中找到设置添加服务添加php web page配置完信息后 首先根据PHP的版本下载并安装对应的Xdebug扩展 我使用的是phpStudy工具,直接在php对应的版本中开启xdebug扩展, 并在php.ini中添加如下…...
DFS/BFS简介以及剪枝技巧
DFS简介 DFS含义 ⭐ DFS,即Depth-first-search,是深度优先搜索的简称。 它的主要思路是一直沿当前分支搜索,当搜索到尽头之后返回,再逐步向其他地方扩散。 我们可以通过一个树形结构说明DFS的遍历顺序 A/ | \B C D/ \ |E…...
LeetCode[15]三数之和
思路: 一开始我想的用哈希表来做,但是怎么想怎么麻烦,最后看解析,发现人家用的双指针,那我来讲一下我这道题理解的双指针。 这道题使用双指针之前一定要给数组进行排序,ok为什么排序?因为我需要…...
高性能计算面经
高性能计算面经 C八股文真景一面凉经自我介绍,介绍一下你做过的加速的模块(叠噪,噪声跟原图有什么关系?)OpenGL和OpenCL有什么区别?**1. 核心用途****2. 编程模型****3. 硬件抽象****4. API设计****5. 典型应用场景****6. 互操作性…...
HTML 标签类型全面介绍
HTML 标签类型全面介绍 HTML(HyperText Markup Language)是构建 Web 页面结构的基础语言。HTML 由不同类型的标签组成,每种标签都有特定的用途。本文将全面介绍 HTML 标签的分类及其用法。 1. HTML 标签概述 HTML 标签通常成对出现…...
【漫话机器学习系列】168.最大最小值缩放(Min-Max Scaling)
在机器学习和数据预处理中,特征缩放(Feature Scaling) 是一个至关重要的步骤,它可以使模型更稳定,提高训练速度,并优化收敛效果。最大最小值缩放(Min-Max Scaling) 是其中最常见的方…...
Spring Boot中对同一接口定义多个切面的示例,分别通过接口方式和注解方式实现切面排序,并对比差异
以下是Spring Boot中对同一接口定义多个切面的示例,分别通过接口方式和注解方式实现切面排序,并对比差异: 一、接口方式实现切面排序 1. 定义接口 // 服务接口 public interface MyService {void methodA();void methodB(); }// 接口实现类…...
基于SpringBoot的高校学术交流平台
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
数据治理的专题库
数据治理专题库的全面解析 一、专题库的定义与定位 数据治理专题库是围绕特定业务领域或场景构建的专业化数据库,其核心在于业务导向性和自主性。与基础库(如人口、法人、地理信息等跨部门核心实体数据)和主题库(如市场监管中的…...
【MathType】MathType安装和嵌入word
MathType 是一款功能强大的数学公式编辑器,广泛应用于学术论文、教材编写、科研报告等领域。它支持多种数学符号、公式排版,并且与 Microsoft Word、Google Docs、WPS 等办公软件兼容,极大地方便了数学公式的输入和编辑 记录一下安装的过程 …...
mediacodec服务启动时加载media_codecs.xml
media.codec服务启动时, 会创建 implementation::Omx 和 implementation::OmxStore, 构造 Omx时, 会解析codec相关的xml文件,一般从会如下目录中, // from getDefaultSearchDirs() { "/product/etc",&quo…...
Scala(三)
本节课学习了函数式编程,了解到它与Java、C函数式编程的区别;学习了函数的基础,了解到它的基本语法、函数和方法的定义、函数高级。。。学习到函数至简原则,高阶函数,匿名函数等。 函数的定义 函数基本语法 例子&…...
kafka 报错消息太大解决方案 Broker: Message size too large
kafka-configs.sh --bootstrap-server localhost:9092 \ --alter --entity-type topics \ --entity-name sim_result_zy \ --add-config max.message.bytes10485880 学习营课程...
APScheduler定时
异步IO 定时(协程) import asyncio import logging from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.triggers.cron import CronTriggerlogging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__)class Schedul…...
[GESP202503 C++六级题解]:P11962:树上漫步
[GESP202503 C++六级题解]:P11962:树上漫步 题目描述 小 A 有一棵 n n n 个结点的树,这些结点依次以 1 , 2 , ⋯ , n 1,2,\cdots,n 1,2,⋯,n 标号。 小 A 想在这棵树上漫步。具体来说,小 A 会从树上的某个结点出发,每⼀步可以移动到与当前结点相邻的结点,并且小 A…...
JavaScript基础-常见网页特效案例
在现代Web开发中,JavaScript不仅是处理业务逻辑的核心工具,也是实现丰富交互体验的关键。通过JavaScript,我们可以轻松地为网页添加各种动态效果和交互特性,从而提升用户体验。本文将介绍几种常见的网页特效案例,并提供…...
数据结构4
day4 5.队列 Queue 5.1 特性 队列是只允许再两端进行插入和删除操作的线性表,在队尾插入,在队头删除,插入的一段被称为“队尾”,删除的一端被称为“队头”。队列包括循环队列(顺序队列)、链式队列。结构:先进先出&…...
Rust 为什么不适合开发 GUI
前言 在当今科技蓬勃发展的时代,Rust 编程语言正崭露头角,逐步为世界上诸多重要基础设施提供动力支持。从存储海量信息到应用于 Linux 内核,Rust 展现出强大的实力。然而,当涉及构建 GUI(图形用户界面)时&…...
DisplayPort版本对比
目前视频接口标准基本上被HDMI和DisplayPort两大标准给瓜分天下了。 (1) HDMI由消费电子厂商主导,最新版本(如HDMI 2.1)理论带宽为48Gbps,主要应用于电视、游戏主机及家庭影音设备。 (2…...
YOLOv12即插即用-Pconv(风车卷积)
1.模块介绍 PinwheelConv(风车状卷积)充分利用了IRST(红外搜索与跟踪)中的高斯分布特性,以极少的参数实现了高效且更大感受野的特性。此外,本文还提出了一种简单而高效的 SD 损失函数,有效缓解了标签 IoU 变化带来的不稳定性。通过与现有卷积模块和损失函数的广泛对比,…...
AI知识补全(十四):零样本学习与少样本学习是什么?
名人说:一笑出门去,千里落花风。——辛弃疾《水调歌头我饮不须劝》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:AI知识补全(十三):注意力…...
Pycharm(十一):字符串练习题
1.输入一个字符串,打印所有偶数位上的字符(下标是0,2,4,6...位上的字符) # 练习题1:输入一个字符串,打印所有偶数位上的字符(下标是0,2,4,6...位上的字符) # 1.键盘录入字符串&…...
设计原则之迪米特法则
一、定义 迪米特法则又称为最少知识原则(Law of Demeter,LoD),是一项用于面向对象设计的基本原则之一。该原则强调一个对象应该对其他对象有最少的了解,即一个类不应该知道太多关于其他类的内部细节。 二、好处 迪米…...
Debian系统_主板四个网口1个配置为WAN,3个配置为LAN
Debian系统_主板四个网口1个配置为WAN,3个配置为LAN 一、重新配置网口 1、查看当前网口的状态 ifconfig 或者 ip link show 或者 ls /sys/class/net 2、修改网络配置文件 sudo vi /etc/network/interfaces 注意WAN口的网关地址如果是192.168.3.1的话,L…...
Spring Boot 快速入手
前言:为什么选择 Spring Boot? 🚀 在现代 Java 开发中,Spring Boot 已成为最流行的后端框架之一。无论是小型 Web 应用、企业级系统,还是微服务架构,Spring Boot 都能提供快速开发、自动配置、轻量级部署的…...
Ubuntu Live USB 如何使用
以下是使用 Ubuntu Live USB 的详细指南,涵盖启动、试用系统、安装系统及常用工具操作: 1. 制作 Ubuntu Live USB • 所需工具: • Ubuntu ISO 镜像(从 官网 下载)。 • U盘(至少 4GB,数据将被…...
基于单片机的音乐播放器系统设计
基于单片机的音乐播放器系统设计是一个综合性较强的电子系统开发项目 系统概述 基于单片机的音乐播放器旨在利用单片机的控制功能,结合音频处理电路、存储单元等,实现音乐的播放、暂停、切换、音量调节等功能,可应用于小型便携式音频设备、电子玩具、智能家居背景音乐系统等…...
HttpClient-01.介绍
一.介绍 通过HttpClient,我们可以在Java程序中构造并发送Http请求。要使用HttpClient,就要导入依赖坐标。 核心API: HttpClient:Http客户端,使用它可以发送http请求。 HttpClients:构建器,使…...
2025年win10使用dockerdesktop安装k8s
一、写作背景 百度了一圈, 要么教程老,很多操作步骤冗余, 要么跑不通,或者提供的链接失效等情况。 二、看前须知 1、安装过程使用的AI辅助, 因为参考的部分博客卡柱了。 2、如果操作过程中遇到卡顿, …...
技术回顾day2
1.获取文件列表 流程:前端根据查询条件封装查询信息,后端接收后进行封装,封装为FileInfoQuery,根据fileInfoQuery使用mybatis的动态sql来进行查询。 2.文件分片上传 每次上传需要上传包括(文件名字,文件,md5值&#…...
软件工程-UML
例图,类图,状态图,顺序图,活动图 目录 例图 类图 状态图 顺序图 活动图 例图 例图由四个元素组成,参与者、用例、系统边界、参与者和用例之间的关系 参与者用一个小人表示,用例用椭圆表示ÿ…...
赛逸展2025“创新引擎”启动:限量席位,点亮科技绿色新征程
当今时代,科技革新与绿色发展已然成为推动社会进步的双引擎。2025第七届亚洲消费电子技术贸易展(赛逸展)敏锐捕捉这一趋势,重磅打造“科技创新专区”,并面向科技、绿色企业吹响限量招募号角。 这个独具特色的专区紧扣…...
前后台系统
前后台系统(Foreground/Background System)是一种常见的嵌入式系统编程模型,尤其是在那些不需要复杂操作系统的简单系统中。这种系统架构通常用于实时性要求不是极端苛刻的环境,但在响应外部事件时仍需要一定的及时性。下面我将详…...
VHT AMPDU
A - MPDU 由一个或多个 A - MPDU 子帧以及可变数量的 EOF填充子帧组成。 在 VHT中,存在如下填充: 一个 A - MPDU 子帧的填充子字段中有 0 - 3 个字节。 EOF 填充字段中有零个或多个 EOF 填充子帧。 EOF 填充子帧中EOF填充字节中有 0 - 3 个字节。 A - MPDU 帧结束前填充(A -…...
Spring框架如何做EhCache缓存?
在Spring框架中,缓存是一种常见的优化手段,用于减少对数据库或其他资源的访问次数,从而提高应用性能。Spring提供了强大的缓存抽象,支持多种缓存实现(如EhCache、Redis、Caffeine等),并可以通过…...
助力 Windows 文件管理:重命名与清理重复文件软件精选
软件介绍 在日常的电脑使用中,高效管理文件至关重要。接下来为大家介绍几款实用软件,能助您轻松搞定文件管理难题。 AdvancedRenamer:全能批量重命名利器 专为 Windows 系统打造的 AdvancedRenamer,功能堪称强大。无论是文本替…...
重建二叉树(C++)
目录 1 问题描述 1.1 示例1 1.2 示例2 1.3 示例3 2 解题思路 3 代码实现 4 代码解析 4.1 初始化 4.2 递归部分 4.3 主逻辑 5 总结 1 问题描述 给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。 例如输入前序遍历序…...
Go+Gin实现安全多文件上传:带MD5校验的完整解决方案
后端 package mainimport ("encoding/json""fmt""log""net/http""os""path/filepath""github.com/gin-contrib/cors""github.com/gin-gonic/gin" )// 前端传来的文件元数据 type FileMetaRe…...
SwanLab Slack通知插件:让AI训练状态同步更及时
在AI模型训练的过程中,开发者常常面临一个难题:如何及时跟踪训练状态?无论是实验超参数的调整、关键指标的变化,还是意外中断的告警,传统的监控方式往往依赖手动刷新日志或反复检查终端,这不仅效率低下&…...
JavaScript元素尺寸与位置
目录 client 家族与 offset 家族 一、client 家族:内容区域 内边距 示例代码 应用场景 二、offset 家族:内容区域 内边距 边框 滚动条 示例代码 应用场景 三、综合应用场景 1. 动态调整元素高度 2. 拖拽元素 3. 判断元素是否在视口内 四…...
IS-IS:单区域集成配置与多区域集成配置
一、IS-IS概述 IS-IS(Intermediate System to Intermediate System) 是一种链路状态内部网关协议(IGP),设计用于自治系统(AS)内部的路由选择。最初由ISO为OSI模型的无连接网络服务(…...
Cesium学习(未完继续)
添加底图 viewer.imageryLayers.addImageryProvider(imageryProvider)常见 ImageryProvider 实现类 ArcGisMapServerImageryProvider:用于从 ArcGIS Server 获取影像数据。 BingMapsImageryProvider:用于从 Bing Maps 获取影像数据。 OpenStreetMapIm…...
【学Rust写CAD】22 双圆径向渐变的结构体(two_circle_radial_gradient.rs)
源码 //two_circle_radial_gradient.rs //! 定义双圆径向渐变的结构体和相关功能/// 表示一个双圆径向渐变的源 /// /// 该结构体描述了两个圆之间的渐变,支持矩阵变换和颜色查找表优化 #[derive(Debug, Clone, PartialEq)] pub struct TwoCircleRadialGradientSou…...
基于SpringAOP面向切面编程的一些实践(日志记录、权限控制、统一异常处理)
前言 Spring框架中的AOP(面向切面编程) 通过上面的文章我们了解到了AOP面向切面编程的思想,接下来通过一些实践,去更加深入的了解我们所学到的知识。 简单回顾一下AOP的常见应用场景 日志记录:记录方法入参、返回值、执…...