Java中的网络IO模型:BIO/NIO/AIO

目录

  • Java IO类型
  • Java网络IO模型:BIO/NIO/AIO
    • 1. Java BIO(同步阻塞)
    • 2. Java NIO(同步非阻塞)
    • 3. Java AIO(异步非阻塞)
  • BIO、NIO、AIO 适用场景分析

Java IO类型

Java IO常见使用场景

  • 磁盘操作: File
  • 字节操作: InputStream 和 OutputStream
  • 字符操作: Reader 和 Writer
  • 对象操作: Serializable
  • 网络操作

Java 中的网络支持

  • InetAddress: 用于表示网络上的硬件资源,即 IP 地址;
  • URL: 统一资源定位符;
  • Sockets: 使用 TCP 协议实现网络通信;
  • Datagram: 使用 UDP 协议实现网络通信。

Java网络IO模型:BIO/NIO/AIO

网络IO操作通常包括两个阶段,如输入操作:

  1. 等待数据准备好:等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的缓冲区
  2. 从内核向进程复制数据:把数据从内核缓冲区复制到应用进程缓冲区

阻塞IO 和 非阻塞IO

程序请求操作系统IO操作后,如果IO资源没有准备好,那么程序该如何处理的问题:前者等待;后者继续执行(并且使用线程一直轮询,直到有IO资源准备好了)

同步IO 和 非同步IO

那么操作系统收到程序请求后的IO操作,开始上述输入操作的第2个步骤,前者不响应,直到IO复制好以后;后者返回一个标记,当IO资源复制好以后,再返回给程序。

1. Java BIO(同步阻塞)

应用程序向操作系统请求网络IO操作,这时应用程序会一直等待;另一方面操作系统收到请求后,也会等待,直到网络上有数据传到监听端口;操作系统在收集数据后,会把数据发送给应用程序; 最后应用程序受到数据,并解除等待状态。

以Socket实现TCP通信为例

在Server服务器端的实现模式,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果没有连接则等待。

利用 TCP 协议进行通信的两个应用程序是有主次之分的,一个是服务器程序,一个是客户端程序,两者的功能和编写方法不太一样。其中 ServerSocket 类表示 Socket 服务器端,Socket 类表示 Socket 客户端。两者之间的交互过程如下:

  • 服务器端创建一个 ServerSocket(服务器端套接字),调用 accept() 方法等待客户端来连接。
  • 客户端程序创建一个 Socket,请求与服务器建立连接。
  • 服务器接收客户的连接请求,同时创建一个新的 Socket 与客户建立连接,服务器继续等待新的请求。
    Java中的网络IO模型:BIO/NIO/AIO_第1张图片

Java BIO模型
Java中的网络IO模型:BIO/NIO/AIO_第2张图片

BIO 问题分析

  • 每个请求都需要创建独立的线程,与对应的客户端进行数据处理。
  • 当并发数大时,需要创建大量线程来处理连接,系统资源占用较大。
    (可以适当使用线程池,解决创建线程过程中的开销的问题)
  • 连接建立后,如果当前线程暂时没有数据可读,则当前线程会一直阻塞在 Read 操作上,造成线程资源浪费。

2. Java NIO(同步非阻塞)

服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求会被注册到多路复用器上,多路复用器 轮询 到有 I/O 请求就会进行处理。

  • 块式IO处理
    Standard IO是对 字节流 的读写,在进行IO之前,首先创建一个流对象,流对象进行读写操作都是按 字节 ,一个字节一个字节的来读或写。
    而NIO把IO抽象成块,类似磁盘的读写,每次IO操作的单位都是一个块,块被读入内存之后就是一个 byte[],NIO一次可以读或写多个字节.

Java NIO模型
Java中的网络IO模型:BIO/NIO/AIO_第3张图片
1. 通道Channel

通道 Channel 是对原 I/O 包中的流的模拟,可以通过它读取和写入数据。通道与流的不同之处在于,流只能在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类),而 通道是双向的,可以用于读、写或者同时用于读写。

通道包括以下类型:

  • FileChannel: 从文件中读写数据;
  • DatagramChannel: 通过 UDP 读写网络中数据;
  • SocketChannel: 通过 TCP 读写网络中数据;
  • ServerSocketChannel: 可以监听新进来的 TCP 连接,对每一个新进来的连接都会创建一个 SocketChannel

2. 缓冲区

发送给一个通道的所有数据都必须首先放到缓冲区中,同样地,从通道中读取的任何数据都要先读到缓冲区中。也就是说,不会直接对通道进行读写数据,而是要 先经过缓冲区 。缓冲区实质上是一个数组,但它不仅仅是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。

缓冲区包括以下类型:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer

3. 选择器

NIO 实现了 IO 多路复用中的 Reactor 模型:一个线程 Thread 使用一个选择器 Selector 通过 轮询的方式去监听多个通道 Channel 上的事件,从而让一个线程就可以处理多个事件。

  • 配置监听的通道 Channel 为非阻塞:那么当 Channel 上的 IO 事件还未到达时,就不会进入阻塞状态一直等待,而是继续轮询其它 Channel,找到 IO 事件已经到达的 Channel 执行。

因为创建和切换线程的开销很大,因此使用一个线程来处理多个事件而不是一个线程处理一个事件具有更好的性能。

同步网络 Reactor模型
Java中的网络IO模型:BIO/NIO/AIO_第4张图片

3. Java AIO(异步非阻塞)

AIO 引入了异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用。

异步网络 Proactor模型
Java中的网络IO模型:BIO/NIO/AIO_第5张图片

  1. Proactor Initiator 创建 Proactor 和 Handler 对象,并将 Proactor 和 Handler 都通过 AsyOptProcessor注册到内核
  2. AsyOptProcessor 处理注册请求,并处理 I/O 操作;
  3. AsyOptProcessor 完成 I/O 操作后通知 Proactor;
  4. Proactor 根据不同的事件类型 回调Handler 进行业务处理;
  5. Handler 完成业务处理

BIO、NIO、AIO 适用场景分析

网络IO类型 适用场景
BIO 适用于 连接数比较小 且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4 之前唯一的选择,程序较为简单容易理解
NIO 适用于 连接数目多且连接比较短 的架构,比如聊天服务器,弹幕系统,服务器间通讯等,编程比较复杂,JDK1.4 开始支持
AIO 适用于 连接数目多且连接比较长 的架构,比如相册服务器,充分调用 OS 参与并发操作,变成比较复杂,JDK7 开始支持

你可能感兴趣的:(Java,java,socket,网络)