I/O模型
写在前面
前面聊完了IO方式, 也就意味着网络数据的收发通道是建立起来了。但业务场景中, 通道本身是不会发送数据的。在常见的网络应用中, server端会创建多个链接以服务更多client, 同时要求各个client尽可能互不影响。这是I/O模型(也就是IO方式+线程模型)要解决的问题。由于加入了线程要素, 接下来首先聊几个流行语。
一、常见词汇
1. 同步/异步
同步/异步是应用和内核之间的协作模式。由于Linux Kernel托管了对所有外设的I/O, 因此对外设的I/O操作都需要通过系统调用完成。一般来说, 应用发起I/O请求, 内核负责I/O响应。所以更严谨来说, I/O请求和I/O响应的协作。在应用发起I/O操作之后, 如果内核立刻开始处理, 这就是同步协作; 如果应用发起I/O之后, 内核并不马上开始处理, 那么就是异步协作。
2. 阻塞/非阻塞
阻塞/非阻塞则强调应用线程发起I/O操作后的状态。为什么应用线程状态? 因为应用开发者需要知道, 操作对当前线程状态的影响。类似地, 不强调内核状态是因为站在软件分层的角度应用不应该关心Kernel。此外, 虽然线程状态与前面所说的协作模式有关, 但是两者描述的对象不同。这个在面试中很容易掉坑, 比如讲讲同步和阻塞的区别。
3. 举个栗子
比如你(应用)用打印机(内核)打印文件
| IO方式 | 实例 | 评价 |
|---|---|---|
| 同步阻塞IO | 你发起请求然后打印机立刻开始工作, 你站在打印机旁边等着啥也不干 | 你投入发请求, 处理请求和接响应的时间 |
| 同步非阻塞IO | 你发起请求然后打印机立刻开始工作, 你继续忙手上的事情, 过了10分钟去拿结果 | 你投入发请求, 检查进度和接响应的时间 |
| 异步阻塞IO | 你发起请求, 打印机就提示你文件已加入打印队列, 但是你就这么看着, 直到打印机把自己的文件打好 | 你投入发请求, 处理请求(老板知道直挠头)和接响应的时间 |
| 异步非阻塞IO | 你发起请求, 打印机提示你10分钟去拿结果 | 你投入发请求和接响应的时间 |
二、server端要点
- 服务于多用户(天南海北都能连接), 因此需要创建多个链接;
- 由于链接的独立性, 每个链接支持独立读写(各个链接的数据不会串门);
- 每个链接是自己创建的, 在数据确定的情况下直接写入即可, 因此独立写入比较明确;
- 链接一有数据尽快读取。这点比较困难,因为读取的数据来自client, client何时写是不确定的, server端需要有一种感知机制;
三、线程池+同步阻塞IO

- 一般由一个线程负责accept新的connection, 而后给每个connection在server端对应一个处理的Thread;
- 由于connection会断开, 而Thread创建成本较高, 因此可以使用ThreadPool来管理;
- 数据接收通过SocketInputStream完成; 没有数据时, 线程处于block状态;
- 数据发送通过SocketOutputStream完成;
- 连接数受线程数限制, 因此支持的链接数非常有限。但由于实现简单, 如果并发连接数可控比如20个上限也可以考虑(比如一些技术验证); 此外, 如果发送的消息比较大(M级别), 由于存在多次复制, 数据发送延迟也会比较明显。
到这里, 想必你已意识到网络应用中server端的三大块–连接管理, IO管理和应用逻辑。而IO管理和应用逻辑对资源的消耗与连接数呈正相关。一请求一线程模式, 随着链接数的上升CPU占用直线上升, 这就是著名的C10K问题。业界认为过多的线程切换, 数据的多次复制均需要CPU参与最终导致了这一结果。于是就有了下面的改进方案。
四、reactor模式
- 数据读取开始前, 先由一个线程(称为reactor)获取链接的ready标记;
- 仅对存在数据的链接读取数据, 数据读取完成后作为一个事件放入一个事件队列(称为EventQueue)中;
- 创建一个处理线程(EventLoop)循环读取事件队列中的而后处理;
- 数据写入时也放入队列中, 由处理线程读取并发送;
- 相比于一请求一线程模式, reactor模式可以使用更少的线程, 节约了CPU的调度时间。此外, IO方式需要增加对ready标记读取支持, 这就是同步非阻塞IO。试想如果数据已经ready, 则意味着内核已经完成数据读取, 只是等待应用发起拷贝而已。因此, 实际的读取过程依然是内存复制完成, 用户线程依然是阻塞的。
- Netty对此做了优化, 做到应用内存与内核共享部分堆外内存, 减少了内核到应用的一次拷贝, 进一步提升性能。以下是reactor模式的几种实现, 本质上是对Reactor线程和EventLoop线程的组合。
1. 单reactor+单 EventLoop

2. 单reactor+N EventLoop

3. (单reactor+N EventLoop) * N
总结
以上就是今天要讲的内容,本文介绍了Java网络应用中的几种IO模型,后续会追更Proactor模式以及AIO相关内容,希望能于在读的你能更好理解IO模型,于我个人能做进一步的整理和总结。
相关文章:
I/O模型
写在前面 前面聊完了IO方式, 也就意味着网络数据的收发通道是建立起来了。但业务场景中, 通道本身是不会发送数据的。在常见的网络应用中, server端会创建多个链接以服务更多client, 同时要求各个client尽可能互不影响。这是I/O模型(也就是IO方式线程模型)要解决的问题。由于加…...
前端必备技术之——AJAX
简介 AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML(现在已经基本被json取代)。通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。AJAX 不是新的编程语言,而是一种将现有的标准组…...
MySQL数据库 各种指令操作大杂烩(DML增删改、DQL查询、SQL...)
文章目录前言一、DML 增删改添加数据修改数据删除数据二、DQL 查询基本查询条件查询聚合函数(count、max、min、avg、sum)分组查询(group by)排序查询(order by)分页查询(limit)DQL 语句练习三、SQLDCL 权限控制约束案例多表查询事务存储引擎字符串函数数值函数日期函数流程函数…...
Java分布式全局ID(一)
随着互联网的不断发展,互联网企业的业务在飞速变化,推动着系统架构也在不断地发生变化。 如今微服务技术越来越成熟,很多企业都采用微服务架构来支撑内部及对外的业务,尤其是在高 并发大流量的电商业务场景下,微服务…...
算法分析与设计之并查集详解
算法分析与设计之并查集1.前言2.并查集的基础2.1.关于动态连通性2.2.动态连通性的应用场景:2.3.对问题建模:2.4.建模思路:2.5.API2.7.Quick-Find算法:2.8.Quick-Union算法:3. 并查集的应用1.前言 本文主要介绍解决动态…...
Linux - 内存性能评估
文章目录概述free 命令指定的时间段内不间断地监控内存的使用情况通过watch与free相结合动态监控内存状况vmstat命令监控内存“sar –r”命令组合小结概述 内存的管理和优化是系统性能优化的一个重要部分,内存资源的充足与否直接影响应用系统的使用性能。在进行内存…...
00后初中辍学,转行程序员后,终于找到了女朋友
大家好,这里是程序员晚枫,今天继续分享我们的读者投稿,如需投稿赚稿费的朋友,请在后台私信我:投稿。下面我们进入正文吧~ 我是一位 00 后,从初一辍学,到目前为止已有 8 年的时间了,在…...
“Vue学习注意事项:掌握核心特性,注意性能优化和第三方库的使用“
Vue是一款易学易用的JavaScript框架,它可以帮助开发者构建动态、高性能的用户界面。Vue的核心概念包括数据绑定、指令、计算属性和组件化,学习Vue需要注意以下几个点:1. 理解Vue的基本概念和用法Vue的基本概念包括模板、组件、数据绑定、计算…...
计算机网络协议详解(二)
文章目录🔥HTTP协议介绍🔥HTTP协议特点🔥HTTP协议发展和版本🔥HTTP协议中URI、URL、URN🔥HTTP协议的请求分析🔥HTTP协议的响应分析🔥MIME类型🔥HTTP协议介绍 HTTP协议介绍 什么是超…...
【CSS】CSS 复合选择器 ② ( 子元素选择器 | 交集选择器 )
文章目录一、子元素选择器1、语法说明2、代码分析3、代码示例二、交集选择器1、语法说明2、代码示例一、子元素选择器 1、语法说明 子元素选择器 可以选择 某个基础选择器 选择出的 元素组 的 直接子元素 ( 亲儿子元素 ) 中 使用基础选择器 选择 元素 ; 子元素选择器语法 : 父选…...
Java集合专题
文章目录框架体系CollectionListArrayListLinkedListVectorSetHashSetLinkedHashSetTreeSetMapHashMapHashtableLinkedHashMapTreeMapPropertiesCollections框架体系 1、集合主要分了两组(单列集合,双列集合) 2、Collection接口有两个重要的子…...
双重差分法(DID):算法策略效果评估的利器
文章目录算法评估DID原理简单实例Python实现算法评估 作为一名算法出身的人,曾长期热衷于算法本身的设计和优化。至于算法的效果评估,通常使用公开数据集做测试,然后对比当前已公开的结果,便可得到结论。 但是在实际落地过程中&…...
【pytorch】使用mixup技术扩充数据集进行训练
目录1.mixup技术简介2.pytorch实现代码,以图片分类为例1.mixup技术简介 mixup是一种数据增强技术,它可以通过将多组不同数据集的样本进行线性组合,生成新的样本,从而扩充数据集。mixup的核心原理是将两个不同的图片按照一定的比例…...
面向对象设计模式:创建型模式之单例模式
1. 单例模式,Singleton Pattern 1.1 Definition 定义 单例模式是确保类有且仅有一个实例的创建型模式,其提供了获取类唯一实例(全局指针)的方法。 单例模式类提供了一种访问其唯一的对象的方式,可以直接访问…...
IsADirectoryError: [Errno 21] Is a directory: ‘.‘
项目场景: 基于YOLOv5的室内场景识别 工具:colab 问题描述 Traceback (most recent call last): File “train.py”, line 630, in main(opt) File “train.py”, line 494, in main d torch.load(last, map_location‘cpu’)[‘opt’] File “/usr/…...
判断三角面片与空间中球体是否相交
文章目录一、问题描述二、解题思路 在做项目时遇到了一个数学问题,即,如何判断给定一个三角面片与空间中某个球体有相交部分?这个问题看似简单,实际处理起来需要一些方法和手段。一、问题描述 已知空间中球体的球心位置center&a…...
继承下的缺省参数值和访问说明符
前言 本文将介绍 C 继承体系下,函数缺省参数的绑定和函数访问说明符的绑定。这些奇怪的问题实际上不应在我们的代码中出现,但它们能帮助我们理解 C 的动态绑定和静态绑定,也能帮助我们更好的通过面试。 缺省参数值 先来看一段代码…...
Spring核心模块—— BeanFactoryPostProcessorBeanPostProcessor(后处理器)
后置处理器前言Spring的后处理器BeanFactoryPostProcessor(工厂后处理器)执行节点作用基本信息经典场景子接口——BeanDefinitiRegistryPostProcessor基本介绍用途具体原理例子——注册BeanDefinition使用Spring的BeanFactoryPostProcessor扩展点完成自定…...
产品新人如何培养产品思维?
什么是产品思维?其实很难定义,不同人有不同的定义。有的人定义为以用户为中心打磨一个完美体验的产品;有的定义为从需求调研到需求上线各个步骤需要思考的点,等等。本文想讨论的产品思维是:怎么去发现问题,…...
「兔了个兔」CSS如此之美,看我如何实现可爱兔兔LOADING页面(万字详解附源码)
💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...
