我是傲骄鹿先生,沉淀、学习、分享、成长。

如果你觉得文章内容还可以的话,希望不吝您的「一键三连」,文章里面有不足的地方希望各位在评论区补充疑惑、见解以及面试中遇到的奇葩问法

目录

一、概述

二、BIO、NIO、AIO 使用场景分析

三、BIO(同步阻塞)

1、简要流程

2、服务端代码案例

3、问题分析

四、NIO(同步非阻塞)

1、NIO Buffer 的基本使用

2、NIO 和 BIO 对比

三、NIO三大核心组件关系

五、AIO

六、BIO、NIO、AIO的对比


一、概述

I/O 模型简单理解为:就是使用什么样的通道进行数据的发送和接收,很大程度上决定了程序通信的性能。Java 支持 3 种网络编程模型:BIO、NIO、AIO。

Java BIO同步并阻塞(传统阻塞型),服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不作任何事情会造成不必要的线程开销。

Java NIO同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求会被注册到多路复用器上,多路复用器轮询到有 I/O 请求就会进行处理。

Java AIO异步非阻塞,AIO 引入了异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用。

我们可以简单通俗的进行如下的理解:

  • 同步阻塞:你到饭馆点餐,然后在那等着,还要一边喊:好了没啊!
  • 同步非阻塞:在饭馆点完餐,就去遛狗了。不过溜一会儿,就回饭馆喊一声:好了没啊!
  • 异步阻塞:遛狗的时候,接到饭馆电话,说饭做好了,让您亲自去拿。
  • 异步非阻塞:饭馆打电话说,我们知道您的位置,一会给你送过来,安心遛狗就可以了。

二、BIO、NIO、AIO 使用场景分析

  • BIO 方式适用于连接数比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4 之前唯一的选择,程序较为简单容易理解。
  • NIO 方式适用于连接数目多且连接比较短的架构,比如聊天服务器,弹幕系统,服务器间通讯等,编程比较复杂,JDK1.4 开始支持。
  • AIO 方式适用于连接数目多且连接比较长的架构,比如相册服务器,充分调用 OS 参与并发操作,变成比较复杂,JDK7 开始支持。

三、BIO(同步阻塞

Java BIO 就是传统的 Java IO 编程,其相关的类和接口在 java.io 包下。

BIO(Blocking I/O):同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时,服务器就会需要启动一个线程来进行处理。如果这个连接不作任何事情就会造成不必要的开销,可以通过线程池机制改善。

1、简要流程

  1. 服务器驱动一个 ServerSocket。
  2. 客户端启动 Socket 对服务器进行通信,默认情况下服务器端需要对每一个客户端建立一个线程进行通信。
  3. 客户端发出请求后,先咨询服务器时候否线程响应,如果没有则会等待,或者被拒绝。
  4. 如果有响应,客户端线程会等待请求结束后,再继续执行。

2、服务端代码案例

public class Server {public static void main(String[] args) throws IOException {//创建线程池ExecutorService executorService = Executors.newCachedThreadPool();//创建serverSocketServerSocket serverSocket = new ServerSocket(6666);for (; ; ) {System.out.println("等待连接中...");//监听,等待客户端连接Socket socket = serverSocket.accept();System.out.println("连接到一个客户端");executorService.execute(() -> handler(socket));}}//编写一个handler方法,和客户端通讯public static void handler(Socket socket) {byte[] bytes = new byte[1024];System.out.println("当前线程信息: " + Thread.currentThread().getName());try {//通过socket获取输入流InputStream inputStream = socket.getInputStream();//循环读取客户端发送的数据while (inputStream.read(bytes) != -1) {System.out.println(Thread.currentThread().getName()+ " : 发送信息为 :"+ new String(bytes, 0, bytes.length));}} catch (IOException e) {e.printStackTrace();} finally {System.out.println("关闭连接");try {socket.close();} catch (IOException e) {e.printStackTrace();}}}
}

3、问题分析

  1. 每个请求都需要创建独立的线程,与对应的客户端进行数据处理。
  2. 当并发数大时,需要创建大量线程来处理连接,系统资源占用较大。
  3. 连接建立后,如果当前线程暂时没有数据可读,则当前线程会一直阻塞在 Read 操作上,造成线程资源浪费。

四、NIO(同步非阻塞

Java NIO 全称 Java non-blocking IO,指的是 JDK 提供的新 API。从 JDK 1.4 开始,Java 提供了一系列改进的输入/输出的新特性,被统称为 NIO,即 New IO,是同步非阻塞的。

NIO 相关类都放在 java.nio 包下,并对原 java.io 包中很多类进行了改写。

NIO 有三大核心部分:Channel(管道)Buffer(缓冲区)Selector(选择器)

NIO 是面向缓冲区编程的。数据读取到了一个它稍微处理的缓冲区,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞的高伸缩性网络。

Java NIO 的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用数据,如果目前没有可用数据时,则说明都不会获取,而不是保持线程阻塞,所以直到数据变为可以读取之前,该线程可以做其他事情。非阻塞写入同理。

1、NIO Buffer 的基本使用

public class BufferTest {public static void main(String[] args) {//同理对应的还有:ByteBuffer,IntBuffer,FloatBuffer,CharBuffer,ShortBuffer,DoubleBuffer,LongBuffer//创建一个Buffer,大小为5IntBuffer buffer = IntBuffer.allocate(5);//存放数据for (int i = 0; i < buffer.capacity(); i++) {buffer.put(i);}//切换成读模式. 读写切换buffer.flip();while (buffer.hasRemaining()) {System.out.println(buffer.get()); // 0 1 2 3 4}}}

2、NIO 和 BIO 对比

  1. BIO 以流的方式处理数据,而 NIO 以块的方式处理数据,块 I/O 的效率比流 I/O 高很多。
  2. BIO 是阻塞的,而 NIO 是非阻塞的。
  3. BIO 基于字节流和字符流进行操作,而 NIO 基于 Channel(通道)和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择器)用于监听多个通道事件(比如连接请求,数据到达等),因此使用单个线程就可以监听多个客户端通道

三、NIO三大核心组件关系

  1. 每个 Channel 对应一个 Buffer。
  2. Selector 对应一个线程,一个线程对应多个 Channel。
  3. 该图反应了有三个 Channel 注册到该 Selector。
  4. 程序切换到那个 Channel 是由事件决定的(Event)。
  5. Selector 会根据不同的事件,在各个通道上切换。
  6. Buffer 就是一个内存块,底层是有一个数组。
  7. 数据的读取和写入是通过 Buffer,但是需要flip()切换读写模式。而 BIO 是单向的,要么输入流要么输出流。

关于Selector、Channel和Buffer详细内容

五、AIO

JDK 7 引入了 Asynchronous I/O,即 AIO。在进行 I/O 编程中,通常用到两种模式:Reactor 和 Proactor 。Java 的 NIO 就是 Reactor,当有事件触发时,服务器端得到通知,进行相应的处理。

AIO 叫做异步非阻塞的 I/O,引入了异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才会启动线程,特点就是先由操作系统完成后才通知服务端程序启动线程去处理,一般用于连接数较多且连接时长较长的应用。

Reactor 与 Proactor

  • 两种 IO 多路复用方案:Reactor and Proactor。
  • Reactor 模式是基于同步 I/O 的,而 Proactor 模式是和异步 I/O 相关的。

由于 AIO 目前应用并不广泛,所以本文只是讲述 AIO 基本介绍。

六、BIO、NIO、AIO的对比

BIO g (Blocking  I/O):同步阻塞 I/O 模式,数据的读取写入必须阻塞在一个线程内等待
其完成。在活动连接数不是特别高(小于单机 1000)的情况下,这种模型是比较不错的,可
以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问
题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面
对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效
的 I/O 处理模型来应对更高的并发量。

NIO  (New  I/O): NIO 是一种同步非阻塞的 I/O 模型,在 Java 1.4 中引入了 NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer 等抽象。NIO 中的 N 可以理解为 Non-blocking,不单纯是 New。它支持面向缓冲的,基于通道的 I/O 操作方法。NIO提供了与传统 BIO 模型中的 Socket 和 ServerSocket 相对应 de 的 SocketChannel 和ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞 I/O 来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。

AIO  (Asynchronous  I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的 IO 模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步 IO 的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO 操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

系列文章持续更新,微信搜一搜「傲骄鹿先生 」,回复【面试】有准备的一线大厂面试资料。

Java IO框架之BIO、NIO、AIO相关推荐

  1. Java IO模型:BIO NIO AIO及netty介绍

  2. Java的IO流 ,BIO NIO AIO 的区别?

    目录 1.在了解不同的IO之前先了解:同步与异步,阻塞与非阻塞的区别: 2.BIO NIO AIO 分别代表什么?(面试简答): 3.BIO和NIO.AIO的区别: 4.java中io流的分类: •  ...

  3. Java IO(BIO, NIO, AIO) 总结

    文章转载自:JavaGuide 目录 BIO,NIO,AIO 总结 同步与异步 阻塞和非阻塞 1. BIO (Blocking I/O) 1.1 传统 BIO 1.2 伪异步 IO 1.3 代码示例 ...

  4. java io流区别_Java中IO流的分类和BIO,NIO,AIO的区别

    到底什么是IO 我们常说的IO,指的是文件的输入和输出,但是在操作系统层面是如何定义IO的呢?到底什么样的过程可以叫做是一次IO呢? 拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目 ...

  5. Java中IO流的分类和BIO,NIO,AIO的区别

    到底什么是IO 我们常说的IO,指的是文件的输入和输出,但是在操作系统层面是如何定义IO的呢?到底什么样的过程可以叫做是一次IO呢? 拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目 ...

  6. IO之 java中BIO NIO AIO原理、区别以及应用

    在本篇文章中,我们主要介绍一下java中的BIO NIO AIO,重点是NIO 先说一下同步.异步.阻塞和非阻塞. 简单来讲,同步和异步是针对内核和应用程序之间的交互而言的:阻塞和非阻塞其实是针对进程 ...

  7. Java的IO:BIO | NIO | AIO

    原文: http://my.oschina.net/bluesky0leon/blog/132361 BIO | NIO | AIO,本身的描述都是在Java语言的基础上的.而描述IO,我们需要从两个 ...

  8. JAVA IO : BIO NIO AIO

    JAVA IO : BIO NIO AIO 同步异步.阻塞非阻塞概念 同步与异步 阻塞与非阻塞 IO VS NIO VS AIO 面向流与面向缓冲 阻塞与非阻塞IO BIO.NIO.AIO的JAVA实 ...

  9. Java之IO,BIO,NIO,AIO知多少?

    开心一笑 [一女人:"我真不放心丈夫,他准备到湖中心水最深的地方把猫扔掉."邻居:"那有什么不放心的?"女人:"猫已回家一钟头了!"] 提出 ...

最新文章

  1. DeepMind 最新论文解读:首次提出离散概率树中的因果推理算法
  2. Ubuntu14.04安装nvidia-docker2
  3. configParser模块详谈
  4. Java 7 Swing:创建半透明和成形的Windows
  5. 学习设计模式之抽象工厂模式
  6. 【工作日报】2019年7月 前端开发工作日报汇总
  7. 机器人操作系统ROS(9)Gazebo物理仿真(摄像头仿真)
  8. 项目异常Too many open files
  9. Vulnhub——JANGOW: 1.0.1
  10. js禁止鼠标右键的菜单事件
  11. kingcms php 漏洞,kingcms5.0/5.1漏洞
  12. 【深度学习】医学图像自动分割的评价指标讲解
  13. 扬长避短,做符合个性特质的事
  14. 地表最强! Unity 5.x 插件合集专用贴 - 更新日期 2015.12.06
  15. 【银行系列第一期】中国人民银行
  16. TFN PM3900 高性能无线电综合测试仪的详细参数
  17. 森林怎么训练野人_迷失森林怎么养野人,来研究下吧
  18. qt 中文转十六进制_QT中10进制数转换为16进制数的代码怎么写?
  19. 设置Julia国内镜像站(北外镜像站,由清华TUNA维护)
  20. LeetCode_70_爬楼梯

热门文章

  1. class的操作:className和classList
  2. 时间复杂度和空间复杂度及多道例题讲解
  3. 【计算机网络】MTU和MSS
  4. 漏洞预警|Apache Karaf 存在远程代码执行漏洞
  5. 栈与队列(逆波兰式)
  6. Git - Gitee码云 使用手册
  7. excel中文件合并F9键
  8. html和word相互转换
  9. [CVPR2021]pixelNeRF: Neural Radiance Fields from One or Few Images
  10. DSC测试仪器校正及检验