ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

一次带你搞懂Java中的BIO|NIO|AIO,你也可以轻松玩转!

2021-06-11 16:02:14  阅读:217  来源: 互联网

标签:BIO Java NIO thread Selector 线程 IO 搞懂 Channel


BIO

Java中BIO也成为同步阻塞IO。

同步阻塞IO模式下,服务器实现模式为一个连接对应一个线程,即:有连接请求从客户端发起时,服务器端就需要创建一个线程进行处理,如果有大量连接时,服务器就需要创建大量线程进行处理。当然可以通过线程池机制改善。

阻塞IO适用场景为:连接数较小且固定的架构模式,这种方式对服务器资源要求比较高,并发局限于应用中,不建议在生产环境使用。

NIO(非阻塞IO)

Java中非阻塞式IO,也叫同步非阻塞IO,其通过通道和缓冲区来读写数据。通过选择器注册和获取已准备好的感兴趣的通道事件。读数据时,有多少数据就读多少数据,读完立即返回,如SocketChannel和ServerSocketChannel、Selector等。

NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题。NIO基于Reactor,当socket有流可读或可写入socket时,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。

也就是说,这个时候,已经不是一个连接就要对应一个处理线程了,而是有效的请求,对应一个线程,当连接没有数据时,是没有工作线程来处理的。

NIO的最重要的地方是,当一个连接创建后,不需要对应一个线程,这个连接会被注册到多路复用器上面。所以,所有的连接只需要一个线程就可以搞定,当这个线程中的多路复用器进行轮询的时候,发现连接上有请求的话,才开启一个线程进行处理,也就是一个请求一个线程模式。

在NIO的处理方式中,当一个请求来的话,开启线程进行处理,可能会等待后端应用的资源(JDBC连接等),其实这个线程就被阻塞了,当并发上来的话,还是会有BIO一样的问题。

Java NIO 由以下几个核心部分组成:

  • Channels
  • Buffers
  • Selectors

虽然Java NIO 中除此之外还有很多类和组件,但是,Channel,Buffer和Selector构成了核心的API。其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类。

读者推荐:并发编程学习笔记

Channel vs Buffer

Channel和Buffer:基本上,所有的IO在NIO中都从一个Channel开始。Channel有点像流,数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中。如:Channel和Buffer有好几种类型。下面是JAVA NIO中的一些主要Channel的实现:FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel。这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。

Java NIO里关键的Buffer实现:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer、MappedByteBuffer(内存映射文件 )。这些Buffer覆盖了能通过IO发送的基本数据类型:byte,short,int,long,float,double和char。

Channel和Buffer使用案例:改代码以随机读写方式打开nio-data.txt文件,一个字节一个字节的把文件内容读入新分配的buf缓存中。

Selector

Selector允许单线程处理多个 Channel。如果应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。例如,在一个聊天服务器中。单线程中使用一个Selector处理3个Channel的图示:

要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。

Selector使用案例:该案例使用Selector已订阅事件的通道进行选择,当订阅事件发生时即可另行开辟线程处理该通道事件。

AIO(异步IO)

Java中的异步IO,通过Future轮询和Callback回调两种方式来使用。

与NIO不同,当进行读写操作时,异步IO情况下,我们只需要直接调用API的read或write方法即可。这两个操作都是异步的。

  • 对于读操作而言,当有流可读时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;
  • 对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。

即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。在JDK1.7中,这部分内容被称作NIO.2,主要在java.nio.channels包下增加了下面四个异步通道:AsynchronousSocketChannel、

AsynchronousServerSocketChannel、AsynchronousFileChannel、AsynchronousDatagramChannel。

Future轮询模式

典型的Java通道类有AsynchronousFileChannel。来看一个例子:

该案例通过异步IO通道AsynchronousFileChannel将文件foobar.txt的内容读入buffer中,在通过Future获取结果。Java将读取文件的操作交给操作系统底层去做,自己只需要知道文件是否读取完毕就好了。其实底层JVM为执行这个任务创建了线程池和通道组。具体可以参考AsynchronousFileChannel的官方说明:

An AsynchronousFileChannel is associated with a thread pool to which tasks are submitted to handle I/O events and dispatch to completion handlers that consume the results of I/O operations on the channel. The completion handler for an I/O operation initiated on a channel is guaranteed to be invoked by one of the threads in the thread pool (This ensures that the completion handler is run by a thread with the expected identity). Where an I/O operation completes immediately, and the initiating thread is itself a thread in the thread pool, then the completion handler may be invoked directly by the initiating thread. When an AsynchronousFileChannel is created without specifying a thread pool then the channel is associated with a system-dependent default thread pool that may be shared with other channels. The default thread pool is configured by the system properties defined by the AsynchronousChannelGroup class.

Callback回调模式

Future其实本质上还是轮循的方式,回调式才是真正的AIO。其基本思想是主线程注册一个CompletionHanlder执行IO操作。CompletionHanlde将带着IO操作的结果返回到主线程中,这个结果会触发它自己的completed或者failed方法(需要重写这两个方法):

  1. void completed(V result, A attachment) - executes if a task completes with a result of type V.
  2. void failed(Throwable e, A attachment) - executes if the task fails to complete due to Throwable e.

callback回调案例:

上面的例子是基于文件的AsynchronousFileChannel,但是基于网络套接字的

AsynchronousServerSocketChannel和AsynchronousSocketChannel也是一样的模式。

标签:BIO,Java,NIO,thread,Selector,线程,IO,搞懂,Channel
来源: https://www.cnblogs.com/QLCZ/p/14875410.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有