BIO与NIO,AIO 总结

1、前备知识:

1.1、同步与异步

  • 同步:同步就是系统发起一个调用后,被调用者未处理完请求之前,调用不返回。

  • 异步: 异步就是系统发起一个调用后,立刻得到被调用者的回应表示已接收到请求,但是被调用者并没有返回结果,此时我们可以处理其他的请求,被调用者通常依靠事件,回调等机制来通知调用者,返回结果。

同步和异步的最大的区别:如果是异步,调用者不需要等待处理结果,被调用者会通过回调等机制来通知调用者其返回结果。

1.2、阻塞和非阻塞

  • 阻塞: 阻塞就是发起一个请求,调用者一直等待请求结果返回,也就是当前线程会被挂起,无法从事其他任务,只有当条件就绪才能继续。

  • 非阻塞: 非阻塞就是发起一个请求,调用者不用一直等着结果返回,继续做其他的操作。

2、BIO(一个连接一个线程)

2.1、前言

  • 一般来说,BIO是采用了一个独立的 Acceptor 线程负责监听客户端的连接,如果只有一个线程,接收到一个用户请求的时候,就会建立通信套接字,并在套接字上面进行读写操作,此时是不能再接收其他客户端的请求的,也就是会导致其他的请求被挂起(阻塞)

  • 想要解决这个问题,往往会采用多线程,一个线程对应一个请求,以此来打破每次只能处理一个请求的弊端。所以他要为每一个请求,都创建一个线程,处理完这个请求的事情后,线程销毁,这种模型叫做:一请求一应答通信模型。但是,线程的创建和销毁都特别耗费CPU的资源,如果并发量够高,系统很有可能因为无法荷载,从而导致宕(dang)机。

为了解决这个问题,引入了伪异步IO的概念。

2.2、伪异步IO

  • 伪异步IO采用了线程池,线程池可以有效的避免大量的线程被创建和销毁的问题,同时可以设置线程池的大小,让线程处于一个固定的范围内,从而系统不会出现宕机的问题,也可以处理多个用户的请求。

2.3、BIO的问题

但是他的底层还是BIO模型,不能从根本上解决问题。(线程被挂起的问题),所以从jdk1.4开始,引入了NIO模型,也叫New IO 模型

3、NIO(一个请求一个线程)

在NIO模型中,引入了三个重要的概念----Channel , Selector,Buffer

3.1、NIO与IO的区别

3.1.1、Buffer(缓冲区)

  • IO是面向流的,NIO是面向Buffer的,Buffer是一个对象,他包含了一些要读入和写出的数据。

  • 老的IO方式,虽然也有buffer区,但是这个Buffer区只是一个流的包装类,其实所有的操作,都是直接操作的流。

  • NIO中所有的数据都是用缓冲区处理,NIO中不管是读,还是写操作,都是与Buffer(缓冲区)打交道

3.1.2、Channel(通道)

这是一个双向的通道,既可以读,也可以写。而IO只能进行读或者是写。无论是读还是写操作,channel通道都是与Buffer区进行交互,且实现了异步读写!(NIO是同步非阻塞,线程是同步的,但是在遇到读操作未完成,或者写操作未完成的时候,线程不会堵塞,后面的继续运行,进行写操作,或者读操作,异步读写!)

3.1.3、Selectors(选择器)

这是NIO独有的,IO要每个连接都对应一个线程。但是NIO把每个连接通过channel(连接通过Channel和selectors进行连接),连接到Selectors上进行管理(一个selectors对应有多个Channel),他只需要使用一个线程,来管理多个通道,因此只需要较少的线程来管理这些请求,从而实现了多路复用。

3.1.4、非阻塞IO

正如上面所说的,IO的线程是阻塞的,NIO的线程是非阻塞的。

3.2、NIO问题

NIO虽然实现了同步不阻塞,但是他的线程还是同步的,在向系统发送操作指令的时候,虽然没有完成,也不会阻塞,但是他要经常向系统发送请求,询问操作是否完成,这样子也耗费了许多的资源。

其次,NIO的Selectors选择器,会轮番的对注册的通道进行轮询,查看是否有请求,这也耗费了许多资源

3、AIO(一个有效请求一个线程)

AIO俗称NIO2,在jdk1.7之后引入,它是异步的非阻塞IO模型。

异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程再进行后续的操作,这也就解决了NIO经常向系统询问操作是否完成的问题

AIO不常用,后面的希望有大神来补充~