所有分类
  • 所有分类
  • 未分类

Java-BIO、NIO、AIO-区别/使用/实例

简介

本文介绍Java的IO模型:BIO、NIO、AIO的区别。

这也是面试常问的问题。

BIO、NIO、AIO区别

BIO (Block IO)NIO (New IO)AIO(Asynchronous I/O)
JDK版本所有版本JDK1.4及之后JDK1.7及之后
异步/阻塞同步阻塞
一个连接一个线程。线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。
数据的读取写入必须阻塞在一个线程内等待其完成。
同步阻塞/非阻塞。
一个请求一个线程。客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。用户进程也需要时不时的询问IO操作是否就绪,这要求用户进程不停的去询问。
异步非阻塞。      
一个有效请求一个线程。用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。
使用场景已成为解决高并发与大量连接、I/O处理问题的有效方式。
比如:Netty、多人聊天室
适用于连接数目多且连接比较长(重操作)的架构。例如:相册服务器。
目前 AIO 的应用还不是很广泛。

为什么Netty用NIO?

Netty 之前也尝试使用过 AIO,不过又放弃了,因为AIO在性能、内存占用上,实际不如NIO。Netty作者的原话如下:

Not faster than NIO(epoll) on unix systems (which is true) 。(在UNIX系统上不比NIO快)
There is no daragream support (不支持数据报)
Unnecessary threading model(too much abstraction without usage) (不必要的线程模型)

详细分析:

  1. Linux上,AIO底层实现仍使用Epoll,没有很好的实现AIO,因此性能上没有明显优势,而且被JDK封装了一层不容易优化。
  2. Netty整体架构是基本reactor模型,而AIO是proactor模型,混合在一起会比较混乱
  3. AIO有个缺点:接收数据需要预先分配缓冲区,而不是NIO那种需要接收时才需要分配缓存,所以对连接数量非常大但流量小的情况,会浪费内存
  4. Linux上AIO不够成熟,处理回调的结果速度跟不上处理需求,供不应求,造成处理速度有瓶颈。比如:外卖员太少,顾客太多。

另外:NIO是一种基于通道和缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存(区别于JVM的运行时数据区),然后通过一个存储在java堆里面的DirectByteBuffer对象作为这块内存的直接引用进行操作。这样能在一些场景显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

实例

BIO

略。

NIO

待填充。

AIO

略。

5

评论4

请先

  1. NIO 同步阻塞/非阻塞怎么理解呢?哪里阻塞了,哪里没有阻塞呢?
    褪墨 2024-06-27 0
    • 阻塞:就一直等着。非阻塞:进程会立即返回,然后会定时去查询结果。
      自学精灵 2024-06-28 0
  2. 讲的有点深,看代码有点懵😂
    150003 2024-04-08 0
    • 了解概念即可,用的比较少。
      自学精灵 2024-04-08 0
显示验证码
没有账号?注册  忘记密码?

社交账号快速登录