AIO异步通信。 NIO同步非阻塞通信。BIO同步阻塞式IO

传统的IO流是阻塞式的:会一直监听一个ServerSocket,在调用read等方法时,他会一直等到数据到来或者缓冲区已满时才返回。调用accept也是一直阻塞到有客户端连接才会返回。每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求。并且多线程处理多个连接。每个线程拥有自己的栈空间并且占用一些 CPU 时间。每个线程遇到外部未准备好的时候,都会阻塞掉。阻塞的结果就是会带来大量的进程上下文切换。

AIO 是彻底的异步通信。

NIO 是同步非阻塞通信。

NIO 是同步阻塞通信。

案例用法:https://blog.csdn.net/u010541670/article/details/91890649?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

假设有这么一个场景,有一排水壶(客户)在烧水。

AIO的做法是,每个水壶上装一个开关,当水开了以后会提醒对应的线程去处理。
NIO的做法是,叫一个线程不停的循环观察每一个水壶,根据每个水壶当前的状态去处理。
BIO的做法是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。


可以看出AIO是最聪明省力,NIO相对省力,叫一个人就能看所有的壶,BIO最愚蠢,劳动力低下。

BIO原理:
单线程:同步阻塞式IO在while循环中服务端会调用accept方法等待接收客户端的连接请求,一旦接收到一个连接请求,就可以建立通信套接字,在这个通信套接字上进行读写操作,此时不能接收其他客户端的连接请求,只能等待同当前连接的客户端的操作执行完成。即典型的一请求一应答通宵模型。

刚开始人们为了解决上面,高并发下服务器建立线程过多而枯竭,有人就想出了使用线程池来控制建立线程的数量,不至于服务器挂掉,于是就有了伪异步的io编程

一(1)、伪异步I/O编程:

  为了改进上面这种一连接一线程的模型,我们可以使用线程池来管理这些线程,实现1个或多个线程处理N个客户端的模型(但是底层还是使用的同步阻塞I/O),通常被称为“伪异步I/O模型“。

 我们知道,如果使用CachedThreadPool线程池(不限制线程数量),其实除了能自动帮我们管理线程(复用),看起来也就像是1:1的客户端:线程数模型,而使用FixedThreadPool我们就有效的控制了线程的最大数量,保证了系统有限的资源的控制,实现了N:M的伪异步I/O模型。

 但是,正因为限制了线程数量,如果发生大量并发请求,超过最大数量的线程就只能等待,直到线程池中的有空闲的线程可以被复用。而对Socket的输入流就行读取时,会一直阻塞,直到发生:1、有数据可读,2、可用数据以及读取完毕,3、发生空指针或I/O异常。

所以在读取数据较慢时(比如数据量大、网络传输慢等),大量并发的情况下,其他接入的消息,只能一直等待,这就是最大的弊端。而后面即将介绍的NIO,就能解决这个难题。

 二、NIO 编程(非阻塞I/O):

在nio中,所有的数据都是通过缓冲区buffer缓冲区来处理的。在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。

原理:客户端发送的连接请求都会注册到多路复用器(Selector)上,多路复用器论询到连接有IO请求时才启动一个线程进行处理。

(1)缓冲区buffer

缓冲区实际是一个数组结构,并提供了对数据结构化访问以及维护读写位置等信息。

8种基本类型都有相应的缓冲区:ByteBuffe、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。他们实现了相同的接口:Buffer

(2)通道channel。

通道不同于流的地方就是通道是双向的,可以用于读、写和同时读写操作。

channel主要有2大类: 1、selectablechannel 用于用户网络的读写。2、 Filechannel 用于文件的操作

fin = new FileInputStream(new File(pathname));
FileChannel channel = fin.getChannel();

(3)多路复用器 Selector。

Selector是Java  NIO 编程的基础。

NIO原理:
1.建立连接:若服务端监听到客户端到连接请求,便为其建立通道(Channel),然后返回继续监听,若同时有多个客户端连接请求到来也可以全部接收,依次为它们建立通道(Channel)。
2.处理数据:若服务端监听到已经创建了通道(Channel)到客户端发来的数据,就会调用对应的接口处理接收到的数据,若同时有多个客户端发来数据也可以依次进行处理
3.同时监听:监听多个客户端的连接请求和接收数据请求的同时,还能监听自己有数据发送。

三、AIO编程:

异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的IO请求都是由OS先完成了再通知服务器应用区启动线程进行处理。

与NIO不同,当进行读写操作时,只需要直接调用API的read或write方法即可。这两种方法均为异步的。

对于读操作而言,当有流可读取的时,操作系统就会将可读的流传入read方法的缓冲区,并通知应用程序。对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。既可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。

应用场景:
BIO方式适用于连接数目比较小且固定的场景,这种方式对服务器资源要求比较高,并发局限于应用中

NIO适合处理连接数目特别多,但是连接比较短小的场景,Jetty,Mina,Zookeeper等都是基于java nio实现

AIO方式使用于连接数目比较多且比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂

原文地址:https://www.cnblogs.com/lgg20/p/12532774.html