重新认识BIO、NIO、IO多路复用、Select、Poll、Epollo它们之间的关系

目录

一、背景

二、名词理解

(1)BIO

(2)NIO

(3)IO多路复用

(4)Select、Poll、Epollo

三、他们之间的关系总结

一、背景

最近又在学习网络IO相关知识,对我们常说的BIO、NIO、IO多路复用、Select、Poll、Epollo之间到底是什么关系,进行重新学习以及总结,特此记录一下。希望对一样迷惑的朋友也有一定的帮助

二、名词理解

(1)BIO

BIO它是Blocking IO的缩写,它的关键的特点就是阻塞IO,什么叫阻塞IO呢,就是你可以理解为它处理连接、读写事件是阻塞的,它采用阻塞方式进行数据读写操作。即当一个线程在执行IO操作时,若没有数据可读,则该线程会一直阻塞等待,直到有数据可读或者超时。如果还不理解我们不妨看看具体的BIO服务端实现的代码,加深自己的理解。

  • BIO服务端代码
package bio;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;/*** bio - server 类** @author chen* @date 2024年03月10日 10:43*/
public class BioServer {public static void main(String[] args) {try {System.out.println("*****服务端启动******");//定义一个ServerSocket对象进行一个服务端的接口注册ServerSocket serverSocket = new ServerSocket(8888);//监听客户端的Socket链接请求Socket socket = serverSocket.accept();//从socket对象中得到一个字节输入流对象InputStream is = socket.getInputStream();//将字节输入流包装成一个缓冲字符输入流(不能直接将字节输入流包装成缓冲字符输入流,先将字节输入流转成字符输入流,再转成缓冲字符输入流)BufferedReader br = new BufferedReader(new InputStreamReader(is));String msg;while ((msg = br.readLine()) != null){System.out.println("服务端收到信息:"+msg);}} catch (IOException e) {e.printStackTrace();}}}

这里我们看到BIO的accept和read方法都是阻塞方法,也就是说线程一旦调用就会进行阻塞

看到这里我们不妨可以思考一下,那我如果想实现多连接处理应该怎么实现?

既然我们一个连接一个线程,那是否我们可以看更多的线程去处理连接,没错,早期的BIO是这样都是这样去处理的,如下代码,加入线程池后的处理

package bio;import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** TODO 类功能描述** @author chen* @date 2024年03月10日 10:43*/
public class BioMoreThreadServer {public static ExecutorService executorService = Executors.newFixedThreadPool(2);public static void main(String[] args) {try {System.out.println("*******服务端启动*********");//注册端口ServerSocket ss = new ServerSocket(8888);//定义一个死循环,负责不断的接收客户端的Socket的连接请求while (true){Socket socket = ss.accept();//创建一个独立的线程来处理这个客户端socket的通信需求
//                new ServerThreadReader(socket).start();//用线程池替代,线程池只是解决了防止频繁创建和销毁线程,并没有解决可以更多的支持连接这个问题(连接数还是有限)executorService.submit(new ServerThreadReader(socket));}} catch (IOException e) {e.printStackTrace();}}}

这里需注意一个细节,加入线程池后,并没有解决能够支持更多的连接的问题,仅仅只是防止线程频繁创建以及销毁,降低系统压力。

看完了BIO我们会提出一个疑问,那如果能够支持更大的连接数呢?

(2)NIO

 NIO是Java 1.4引入的新的IO模型,它采用了多路复用器(Selector)机制,通过少量线程同时管理多个通道,实现了单线程同时处理多个请求的效果。NIO具有高并发性、高吞吐量和更高的可靠性,适合处理连接数多且连接时间较短的场景。NIO的核心组件包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。选择器允许程序同时等待多个通道上的事件,如连接、数据到达等。

从我个人理解的角度,就是新的网络IO模型,增加了在网络IO读取过程中的一些特性,例如非阻塞、高吞吐、高并发性。那么他跟IO多路复用有什么关系呢?

(3)IO多路复用

IO多路复用(IO Multiplexing)一种同步IO模型,单个进程/线程就可以同时处理多个IO请求。一个进程/线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出cpu。多路是指网络连接,复用指的是同一个进程/线程。

这里从我个人的角度理解,以盖房子为例,NIO是一个基础,提供了大量的基础工具(通道[Channel]、缓冲区[Buffer]和选择器[Selector]等等),就像一个我们要盖房子的各种工具已经给你备好了,接下来我们要盖一个怎样的房子(IO多路复用),相当于我们用NIO的技术实现了IO多路复用,如果没有NIO本身这项技术的支持,就不可能实现IO多路复用。

IO多路复用的代码实现

package nio;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;/*** TODO 类功能描述** @author chen* @date 2024年03月10日 13:01*/
public class NioServer {public static void main(String[] args) {try {ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);serverSocketChannel.bind(new InetSocketAddress(8888));Selector selector = Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// 无限判断当前线程状态,如果没有中断,就一直执行while内容。while(!Thread.currentThread().isInterrupted()){// 获取准备就绪的channelif (selector.select() == 0) {continue;}// 获取到对应的 SelectionKey 对象Set<SelectionKey> keys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = keys.iterator();// 遍历所有的 SelectionKey 对象while (keyIterator.hasNext()){// 根据不同的SelectionKey事件类型进行相应的处理SelectionKey key = keyIterator.next();if (!key.isValid()){continue;}if (key.isAcceptable()){accept(serverSocketChannel,selector,key);}if(key.isReadable()){read(key);}// 移除当前的keykeyIterator.remove();}}} catch (Exception e) {e.printStackTrace();}}private static void read(SelectionKey key) {try {SocketChannel socketChannel = (SocketChannel) key.channel();//清除缓冲区,准备接受新数据ByteBuffer readBuffer = ByteBuffer.allocate(1024);//调整缓冲区大小为1024字节int numRead = socketChannel.read(readBuffer);;String str = new String(readBuffer.array(),0,numRead);System.out.println("read String is: " + str);}catch (Exception e){e.printStackTrace();}}private static void accept(ServerSocketChannel serverSocketChannel, Selector selector, SelectionKey key) {try {SocketChannel socketChannel = serverSocketChannel.accept();socketChannel.configureBlocking(false);// 注册客户端读取事件到selectorsocketChannel.register(selector, SelectionKey.OP_READ);System.out.println("client connected " + socketChannel.getRemoteAddress());}catch (Exception e){e.printStackTrace();}}
}

那这个时候IO多路复用算是明白了 ~~

那此时有提出一个疑问:那么IO多路复用跟我们常说的Select、Poll、Epollo又有什么关系?

(4)Select、Poll、Epollo

Select、Poll、Epollo的概念我这里就不一一叙说

总结起来他们就是操作系统函数,不同的操作系统(window、linux)有不同的实现,而且这项技术是不断演化,从早期的Select、演化到Poll、再到Epollo。上面讲到IO多路复用能够使用一个线程监听连接、读写事件,它们在操作系统底层是如何实现的呢?(任何的Java逻辑都是会回归操作系统,例如Java的创建线程,底层也是调用操作系统函数进行线程的创建)其实我们可以追到Select方法的源码,最终会调用本地方法,这里答案也就揭晓了,这三个操作系统函数,是操作系统帮我实现能够使用一个线程监听多个事件的功能,它们是实现IO多路复用的在操作系统层面的基石。

protected int doSelect(long var1) throws IOException {if (this.channelArray == null) {throw new ClosedSelectorException();} else {this.timeout = var1;this.processDeregisterQueue();if (this.interruptTriggered) {this.resetWakeupSocket();return 0;} else {this.adjustThreadsCount();this.finishLock.reset();this.startLock.startThreads();try {this.begin();try {this.subSelector.poll();} catch (IOException var7) {this.finishLock.setException(var7);}if (this.threads.size() > 0) {this.finishLock.waitForHelperThreads();}} finally {this.end();}this.finishLock.checkForException();this.processDeregisterQueue();int var3 = this.updateSelectedKeys();this.resetWakeupSocket();return var3;}}}

三、他们之间的关系总结

最后我画一张图来总结它们的关系

NIO本身这项技术本身是一个大的基石,我们利用了这个基石实现了IO多路复用,而Select、Poll、Epollo这些操作系统函数,是我们操作系统层面的基石,借助这种机制能够帮我们实现事件监听,实现单个线程处理多个事件。从而实现IO多路复用机制,这样就解决了BIO连接数的限制,能够支持处理更多的连接。

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

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

相关文章

C++中的friend关键字

C中的friend关键字允许其他类或函数访问私有和受保护成员。使用friend是一种破坏封装的做法&#xff0c;但在某些情况下&#xff0c;它提供了必要的灵活性。 friend函数 定义&#xff1a;允许一个普通函数访问类的私有&#xff08;private&#xff09;和受保护&#xff08;prot…

Android FrameWork 学习路线

目录 前言 学习路线&#xff1a; 1.基础知识 2、AOSP 源码学习 3. AOSP 源码编译系统 4. Hal与硬件服务 5.基础组件 6. Binder 7. 系统启动过程分析 8. 应用层框架​编辑 9. 显示系统 10. Android 输入系统 11. 系统应用 前言 Android Framework 涉及的行业相当广…

Unity2019.2.x 导出apk 安装到安卓Android12+及以上的系统版本 安装出现-108 安装包似乎无效的解决办法

Unity2019.2.x 导出apk 安装到安卓Android12及以上的系统版本 安装出现-108 安装包似乎无效的解决办法 导出AndroidStudio工程后 需要设置 build.gradle文件 // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAINbuildscript {repositor…

【数据结构】二叉树OJ题(C语言实现)

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…

android studio 连接mumu模拟器调试

1、打开mumu模拟器 2、在Android Studio 中 控制台 cd 到 sdk 目录下 platform-tools 文件夹&#xff0c;有一个adb.exe 可运行程序 一般指令&#xff1a; adb connect 127.0.0.1:7555 但是这个执行在window环境下可能会报错 解决方法是在 adb 之前加 ".\", 问题…

nRF52832——内部温度传感器与随机数产生

nRF52832——内部温度传感器与随机数产生 内部温度传感器温度传感寄存器温度传感器电气特征温度传感器库函数编程 随机数产生器随机数发生器寄存器随机数发生器库函数编程库函数使用流程RNG 工程搭建使用 内部温度传感器 在 nrf52xx 系列芯片内部&#xff0c;包含一个内部温度…

IDEA创建Sping项目只能勾选17和21,没有Java8?

解决办法: 替换创建项目的源 我们只知道IDEA页面创建Spring项目&#xff0c;其实是访问spring initializr去创建项目。故我们可以通过阿里云国服去间接创建Spring项目。将https://start.spring.io/或者http://start.springboot.io/替换为 https://start.aliyun.com/

使用 Python 编写程序保护您的眼睛

眼睛&#xff0c;是心灵的窗户&#xff0c;生活在数字时代的我们&#xff0c;眼睛首当其冲地承受冲击。盯着电脑屏幕成为我们日常工作和学习的一部分&#xff0c;导致用眼过度。那如何减少对眼睛的伤害&#xff0c;应该如何保护眼睛&#xff1f; 用眼应控制时间&#xff0c;自…

C语言字符函数和字符串函数详解

Hello, 大家好&#xff0c;我是一代&#xff0c;今天给大家带来有关字符函数和字符串函数的有关知识 所属专栏&#xff1a;C语言 创作不易&#xff0c;望得到各位佬们的互三呦 一.字符函数 在C语言中有一些函数是专门为字符设计的&#xff0c;这些函数的使用都需要包含一个头文…

如何用人工智能实现客户服务营销?实用指南与关键技巧一网打尽

在不断发展的营销领域&#xff0c;创意是成功营销活动的生命线。火花点燃兴趣&#xff0c;吸引受众&#xff0c;推动参与。但是&#xff0c;如果有一种方法可以利用技术来提升创意&#xff0c;那会怎样呢&#xff1f;生成式人工智能&#xff08;Generative AI&#xff09;是一种…

数据结构与算法----复习Part 16 (并查集)

本系列是算法通关手册LeeCode的学习笔记 算法通关手册&#xff08;LeetCode&#xff09; | 算法通关手册&#xff08;LeetCode&#xff09; (itcharge.cn) 目录 并查集&#xff08;Union Find&#xff09; 基于数组实现的快速查询并查集 基于森林实现的快速合并并查集 路径…

51单片机-AT24C02(I2C总线)

目录 一&#xff0c;介绍及元件工作原理 7.时序结构&#xff08;重要&#xff09; 8.i2C总线数据帧&#xff08;重要&#xff09; 二&#xff0c;应用 一&#xff0c;介绍及元件工作原理 1.元件介绍 2.存储器 3.地址总线和数据总线 地址总线只能一次选中一行 4.引脚及应用…

三次握手seq和ack的流程 TCP协议栈seq和ack深层理解

☆ 大家可以把想了解的问题在评论发给我?我会根据问题补充到后面 ☆ 三次握手seq和ack的流程 是的,在TCP/IP协议中,三次握手过程确实涉及到序列号(Sequence Number, 简称Seq)和确认号(Acknowledgment Number, 简称Ack)的交换。这个过程是为了建立可靠的连接,确保数据能…

Python基础(七)之数值类型字典

Python基础&#xff08;七&#xff09;之数值类型字典 1、简介 字典&#xff08;dict&#xff09;&#xff0c;Dictionary:是一种可变类型&#xff0c;可以存储任意类型的元素&#xff0c;如列表、字符串、元组等。 字典是无序的&#xff0c;所以不支持索引和切片。字典以键值…

CSS中如何设置单行或多行内容超出后,显示省略号

1. 设置超出显示省略号 css设置超出显示省略号可分两种情况&#xff1a; 单行文本溢出显示省略号…多行文本溢出显示省略号… 但使用的核心代码是一样的&#xff1a;需要先使用 overflow:hidden;来把超出的部分隐藏&#xff0c;然后使用text-overflow:ellipsis;当文本超出时…

软考 系统架构设计师之回归及知识点回顾(7)

接前一篇文章&#xff1a;软考 系统架构设计师之回归及知识点回顾&#xff08;6&#xff09; 11. 云计算 背景 大数据和云计算已成为IT领域的两种主流技术。“数据是重要资产”这一概念已成为大家的共识&#xff0c;众多公司争相分析、挖掘大数据背后的重要财富。同时学术界、…

哔哩哔哩后端Java一面

前言 作者&#xff1a;晓宜 个人简介&#xff1a;互联网大厂Java准入职&#xff0c;阿里云专家博主&#xff0c;csdn后端优质创作者&#xff0c;算法爱好者 最近各大公司的春招和实习招聘都开始了&#xff0c;这里分享下去年面试B站的的一些问题&#xff0c;希望对大家有所帮助…

第十二届蓝桥杯EDA省赛真题分析

前言&#xff1a; 第十二届蓝桥杯EDA比赛用的是AD软件&#xff0c;从第十四届起都是使用嘉立创EDA专业版&#xff0c;所以在这里我用嘉立创EDA专业版实现题目要求。 一、省赛第一套真题题目 主观题整套题目如下&#xff1a; 试题一&#xff1a;库文件设计&#xff08;5分&am…

VS Code 配置类似浏览器中的垂直标签页功能

参考&#xff1a;Dominik Weber - 2022.06.25 (注&#xff1a;原文中的配置有些过时了&#xff0c;所以根据 VS Code 的最新版本进行了调整。) 原作者非常喜欢垂直标签页&#xff0c;只要有可能&#xff0c;就都会使用它们。他主要在浏览器&#xff08;Firefox&#xff09;和…

Python之Web开发中级教程----ubuntu中下载安装Postman

Python之Web开发中级教程----ubuntu中下载安装Postman PostMan 是一款功能强大的网页调试与发送网页 HTTP 请求的 Chrome 插件&#xff0c;可以直接去对我们写出来的路由和视图函数进行调试&#xff0c;作为后端程序员是必须要知道的一个工具。 查看ubuntu系统中是否已经安装了…