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

IO

什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。单独的程序一般是让系统为它们完成大部分的工作。

 在 Java 编程中,直到最近一直使用 流 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接触。它也在内部使用,用于将对象转换为字节,然后再转换回对象。

 

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

 

AIO 是彻底的异步通信。BIO 是同步阻塞通信。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。

1.选择器Selector是Java  NIO同步非阻塞 编程的基础。

 

2.选择器Selector是NIO中的重要技术之一。它与SelectableChannel联合使用实现了非阻塞的多路复用。使用它可以节省CPU资源,提高程序的运行效率。

 

3."多路"是指:服务器端同时监听多个“端口”的情况。每个端口都要监听多个客户端的连接。

4.使用了多路复用,只需要一个线程就可以处理多个通道,降低内存占用率,减少CPU切换时间,在高并发、高频段业务环境下有非常重要的优势

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参与并发操作,编程比较复杂

 

posted @ 2020-03-20 16:54  威兰达  阅读(459)  评论(0编辑  收藏  举报