BIO

  • 最传统的网络通信模型
  • 同步堵塞的

    步骤

  1. server 端有个 serverSocket 监听端口
  2. 一个 客户端 socket 对监听端口发起连接,那么 serverSocket 创建一个工作线程和socket 来与客户端的 socket 进行同步阻塞式的数据通信

    缺点

  3. 一个客户端 socket 连接,serverSocket 就要创建一个工作线程和socket 进行数据通信,如果客户端 socket 过多,服务端会创建大量线程,服务器会卡死

  4. 即使使用线程池来负责
    1. 限制了服务端的客户端通信数量
    2. 即使这段通信长期没有交互,浪费资源

NIO

  • 基于 Reactor 模型的同步非堵塞IO

    步骤

  1. 服务端有一个 selector 线程
  2. 一个客户端 socket 进行连接,会创建一个 channel 注册到 selector 上
  3. selector 会轮询这些注册的 channel,当channel 有读写事件,即客户端进行了数据传输,selector 会获取对应的 channel
  4. selector 会创建一个工作线程(可以用线程池),通过 buffer 与 channel 进行同步非堵塞的数据交互,然后通过 channel 将响应返回客户端
  5. 然后工作线程销毁(或者放回线程池)

优缺点

  • NIO 通过内存中的channel 和 selector 线程和若干个少量的工作线程就可以与大量的客户端进行连接
  • 同步,就是工作线程还是需要对 channel 的数据进行读取、写入,这个过程是同步的
  • 非堵塞,就是不论多少客户端的连接和请求都能进来,只要注册对应的 channel ,selector 轮询到有事件的 channel,就会开一个工作线程进行处理

AIO

  • AIO是基于Proactor模型的,就是异步非阻塞模型。

步骤

  • 每个连接发送过来的请求,都会绑定一个buffer,然后通知操作系统去异步完成读,此时你的程序是会去干别的事儿的,等操作系统完成数据读取之后,就会回调你的接口,给你操作系统异步读完的数据。
  • 然后你对这个数据处理一下,接着将结果往回写。
  • 写的时候也是给操作系统一个buffer,让操作系统自己获取数据去完成写操作,写完以后再回调通知你。

同步阻塞、同步非阻塞、异步非阻塞

  • BIO:同步阻塞。这个其实不是针对网络编程模型来说的,是针对文件IO操作来说的。因为用BIO的流(FileInputStream)读写文件,工作线程发起个IO请求直接卡住,必须等着搞完了这次IO才能返回
  • NIO: 同步非阻塞?就是说工作线程通过 NIO 的 FileChannel 发起个文件IO操作,发起之后就返回了,工作线程可以干别的事,这就是非阻塞。但是接下来工作线程还得不断的去轮询操作系统,看IO操作完事了没有。
  • AIO为啥是异步非阻塞?就是说通过AIO发起个文件IO操作之后,你立马就返回可以干别的事儿了,接下来你也不用管了,操作系统自己干完了IO之后,告诉你说ok了。同步就是自己还得主动去轮询操作系统,异步就是操作系统反过来通知你。


    你也可以基于AIO的文件读写的api去读写磁盘文件,你发起一个文件读写的操作之后,交给操作系统,你就不去管他了,直到操作系统自己完成之后,会来回调你的一个接口,通知你说,ok,这个数据读好了,那个数据写完了