700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Java IO框架之BIO NIO AIO

Java IO框架之BIO NIO AIO

时间:2021-10-21 07:29:12

相关推荐

Java IO框架之BIO NIO AIO

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

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

目录

一、概述

二、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、简要流程

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

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、问题分析

每个请求都需要创建独立的线程,与对应的客户端进行数据处理。当并发数大时,需要创建大量线程来处理连接,系统资源占用较大。连接建立后,如果当前线程暂时没有数据可读,则当前线程会一直阻塞在 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 对比

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

三、NIO三大核心组件关系

每个 Channel 对应一个 Buffer。Selector 对应一个线程,一个线程对应多个 Channel。该图反应了有三个 Channel 注册到该 Selector。程序切换到那个 Channel 是由事件决定的(Event)。Selector 会根据不同的事件,在各个通道上切换。Buffer 就是一个内存块,底层是有一个数组。数据的读取和写入是通过 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,不过又放弃了。

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。