1.BIO、NIO和AIO

博客介绍了AIO(NIO 2.0),它是异步非阻塞的,由操作系统完成后回调通知服务端程序启动线程处理,适用于连接数多且连接时间长的应用,JDK7开始支持,还提及会对BIO、NIO、AIO进行对比。
BIO(Blocking IO)
同步阻塞模型,一个客户端连接对应一个处理线程
缺点:
1、IO代码里read操作是阻塞操作,如果连接不做数据读写操作会导致线程阻塞,浪费资源
2、如果线程很多,会导致服务器线程太多,压力太大。
应用场景:BIO 方式适用于连接数目比较小且固定的架构, 这种方式对服务器资源要求比较高,但程序简单易理解。
 
 
NIO(Non Blocking IO)
同步非阻塞,服务器实现模式为一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到多路复用器selector上,多路复用器轮询到连接有IO请求就进行处理。
I/O多路复用底层一般用的Linux API(select,poll,epoll)来实现,他们的区别如下表
 
应用场景:
NIO方式适用于连接数目多且连接比较短(轻操作) 的架构, 比如聊天服务器, 弹幕系统, 服务器间通讯,编程比较复杂, JDK1.4 开始支持
 
NIO有三大核心组件,Channel、Buffer、Selector
 
1、channel 类似于流,每个 channel 对应一个 buffer缓冲区,buffer 底层就是个数组
2、channel 会注册到 selector 上,由 selector 根据 channel 读写事件的发生将其交由某个空闲的线程处理
3、selector 可以对应一个或多个线程
4、NIO 的 Buffer 和 channel 都是既可以读也可以写
 
NIO服务端程序详细分析:
1、创建一个 ServerSocketChannel 和 Selector ,并将 ServerSocketChannel 注册到 Selector 上
2、 selector 通过 select() 方法监听 channel 事件,当客户端连接时,selector 监听到连接事件, 获取到 ServerSocketChannel 注册时绑定的 selectionKey
3、selectionKey 通过 channel() 方法可以获取绑定的 ServerSocketChannel
4、ServerSocketChannel 通过 accept() 方法得到 SocketChannel
5、将 SocketChannel 注册到 Selector 上,关心 read 事件
6、注册后返回一个 SelectionKey, 会和该 SocketChannel 关联
7、selector 继续通过 select() 方法监听事件,当客户端发送数据给服务端,selector 监听到read事件,获取到 SocketChannel  注册时绑定的 selectionKey
8、selectionKey 通过 channel() 方法可以获取绑定的 socketChannel
9、将 socketChannel 里的数据读取出来
10、用 socketChannel 将服务端数据写回客户端
 
总结:NIO模型的selector 就像一个大总管,负责监听各种IO事件,然后转交给后端线程去处理NIO相对于BIO非阻塞的体现就在,BIO的后端线程需要阻塞等待客户端写数据(比如read方法),如果客户端不写数据线程就要阻塞,NIO把等待客户端操作的事情交给了大总管 selector,selector 负责轮询所有已注册的客户端,发现有事件发生了才转交给后端线程处理,后端线程不需要做任何阻塞等待,直接处理客户端事件的数据即可,处理完马上结束,或返回线程池供其他客户端事件继续使用。还有就是 channel 的读写是非阻塞的。
 
 

AIO(NIO 2.0)

异步非阻塞, 由操作系统完成后回调通知服务端程序启动线程去处理, 一般适用于连接数较多且连接时间较长的应用

应用场景:

AIO方式适用于连接数目多且连接比较长(重操作) 的架构,JDK7 开始支持

 

 

BIO、 NIO、 AIO 对比:

 
 
代码示例见码云: https://gitee.com/ex-huh001/netty.git
 
### Java IO模型:BIONIOAIO的工作原理及区别 #### 1. BIO(Blocking IO) BIO 是传统的阻塞式输入输出模型。在这种模型下,客户端服务端之间的通信是基于 Socket 连接的。服务端通过 `ServerSocket` 接收请求并为每个连接分配一个新的线程来处理该请求。如果某个连接处于空闲状态或没有数据可读取时,对应的线程会被阻塞直到有新的数据到来[^3]。 这种方式的主要缺点在于高并发情况下性能较差——因为每一个新建立起来的 socket 都需要占用独立的操作系统级别的线程资源来进行管理维护;而当大量短时间内的瞬时流量涌入服务器时很容易造成 OOM(Out Of Memory),即内存溢出问题发生。 ```java // 创建 ServerSocket 并绑定到指定端口 ServerSocket server = new ServerSocket(port); while(true){ // accept方法会一直等待直至有一个客户机尝试连接进来为止 Socket client = server.accept(); // 对于每次接受到的新socket都启动一个单独的thread去负责后续交互逻辑执行过程中的所有事情。 Thread t=new HandlerThread(client); t.start(); } ``` #### 2. NIO(Non-blocking IO) 相比之下,NIO 则采用了完全不同的设计理念—非阻塞性质以及多路复用技术相结合的形式实现了更加高效的I/O 处理能力 。其核心组件包括 Channel(通道), Buffer(缓冲区), Selector(选择器)[^2]: - **Channel**: 类似传统流的概念但是功能更为强大因为它不仅可以像以前那样单纯地用来传输字节还可以直接映射文件的部分区域甚至整个磁盘分区成为内存映象从而极大地提高了效率; - **Buffer**: 数据容器,所有的数据都是存放在 buffer 中再经过 channel 发送出去或者接收回来 ; - **Selector**: 负责监控多个注册在其上的channel的状态变化情况比如是否有新的连接到达?已存在的某些链接是否变得可读等等事件的发生与否进而决定何时采取行动. 下面是一个简单的例子展示如何利用selector机制监听来自不同source的数据: ```java Selector selector=Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); for (;;){ int readyChannels = selector.select(); if (readyChannels ==0 ) continue; Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()){ SelectionKey key=keyIterator.next(); if(key.isAcceptable()){//a connection was accepted by the ServerSocketChannel. ... }else if(key.isReadable()){ //there is data to read from this channel. ... } keyIterator.remove();//remove current selectionkey after processing it. } } ``` #### 3. AIO(Asynchronous IO) 最后一种就是异步 I/O 模型(AIO) , 它允许应用程序发起一个 I/O 请求之后立刻返回继续干别的活儿去了而不必关心什么时候能够得到结果;等到真正的硬件层面完成了相应的动作后再通知应用层说:"嘿!你的那个任务我已经搞定了哦~"这样做的好处显而易见那就是进一步解放了 CPU 让它可以专注于计算密集型的任务而不是被一堆琐碎的小事缠身无法自拔[ ^1 ] . 不过值得注意的是尽管听起来很美好但实际上目前主流操作系统对该特性的支持程度并不理想再加上 java 自己内部实现也存在诸多局限性因此除非特殊需求否则一般不会优先考虑使用此方案. --- ### 各种模型对比表 | 特征 | BIO | NIO | AIO | |------------|-------------------------|------------------------------|-----------------------------| | 是否阻塞 | Yes | No | No | | 编程复杂度 | Low | Medium | High | | 执行效率 | Poor under high load | Good overall performance | Best theoretical throughput | | 应用场景 | Suitable for low loads| Ideal choice for medium-high| Rarely used due complexity | --- ### 结论 综上所述,BIO适用于低负载的应用程序环境中,而对于那些追求极致效能并且愿意承担额外开发成本的人来说则应该转向研究学习掌握NIO乃至更高阶的技术领域-AIO才是正道所在!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值