- BIO(blocking io,同步阻塞)
场景:客户端向服务端发送请求,服务端会为每个客户端建立一个线程来响应,问题来了,如果客户端出现了延时等异常,服务端为客户端建立的线程,就会一直出于等待状态,这个线程就会占用很长时间(因为数据的准备和处理都在这个线程上完成),更糟糕的是,如果有大量并发访问,服务器就会建立大量线程响应,引起服务器资源枯竭。
BIO的网络编程模型基本是C/S模型,即两个进程间的通信。
服务端提供IP和监听端口,客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功,双方就可以通过套接字进行通信。
传统的同步阻塞模型开发中,serverSocket负责绑定ip地址,启动监听端口;socket负责发起连接操作,连接成功后,双方通过输入流和输出流进行同步阻塞式通信。
BIO的通信模型:
采用BIO通信模型的服务端,通常由一个独立的acceptor线程负责监听客户端的连接,它收到客户端连接请求后为每个客户端创建一个新的线程进行链路处理,处理完成后,通过输出流返回应答给客户端,线程销毁。即典型的一请求一应答通信模型。
通信模型图:
伪异步I/0编程
可以通过线程池管理。
BIO的缺点:
在读取数据较慢(数据量大、网络传输慢等),大量并发情况下,其他接入的消息,只能一直等待,这就是最大的弊端。
- NIO(not-blocking io,同步非阻塞)
JDK1.4中引入java.io.nio.*包中引入新的java i/o库,目的是提高速度。实际上,旧的i/o已经使用nio重新实现过,即使我们不显式的使用nio编程,也能从中受益。速度的提高在文件i/o和网络i/o中都可能发生,我们只讨论后者。
Nio最重要的一个地方是当一个连接创建后,不需要对应一个线程,这个连接会被注册到多路复用器上面,所以所有的连接只需要一个线程就可以搞定,当这个线程中的多路复用器进行轮询的时候,发现连接上有请求的话,才开启一个线程进行处理,就是一个请求一个线程模式。
在nio的处理方式中,当一个请求过来时,开启线程进行处理,可能会等待后端应用的资源,其实这个线程就被阻塞了,当并发上来的时候,也会有bio一样的问题。
模型图:
- AIO(Asynchronous io,异步非阻塞)
与nio不同的是,当进行读写操作时,只需调用api的read或write方法即可。这两种方法都是异步的。
读
当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序。
写
当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。
可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。
- 三者区别
BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
- 三者适用场景
BIO:适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
NIO:适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
AIO:适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
原文地址:https://www.cnblogs.com/keeplearningclc/p/10976296.html