【README】
本文介绍了 3种 java io模型,包括 BIO,NIO, AIO;
IO模型名称 | 描述 | 工作原理 |
BIO-Blocking IO | 同步并阻塞式IO | 一个服务器线程处理一个客户端连接 |
NIO-Non-blocking IO | 同步非阻塞式IO | 一个服务器线程处理多个客户端连接,使用io多路复用(选择器); |
AIO-Asynchronous IO | 异步非阻塞式IO |
【1】应用场景
- 1)BIO方式:适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序简单易理解。
- 2)NIO方式:适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,弹幕系统,服务器间通讯等。编程比较复杂,JDK1.4开始支持。 (Netty是基于NIO的)
- 3) AIO方式:适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。(不常用)
【1.1】BIO代码实现
1)服务端:
/**
* @Description 阻塞式IO服务器
* @author xiao tang
* @version 1.0.0
* @createTime 2022年08月13日
*/
public class BIOServer {
public static void main(String[] args) throws IOException {
// 创建一个线程池
ExecutorService threadPool = Executors.newCachedThreadPool();
int order = 0;
// 创建 服务器 套接字
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("服务器启动成功.");
while(true) {
System.out.println("等待客户端请求");
Socket socket = serverSocket.accept(); // 没有客户端请求,accept阻塞
System.out.printf("客户端[%d]请求建立连接\n", ++order);
final int orderCopy = order;
threadPool.execute(()->{
handler(socket, orderCopy);
});
}
}
/**
* @description 与客户端通讯
* @param socket 连接套接字
* @author xiao tang
* @date 2022/8/13
*/
public static void handler(Socket socket, int order) {
byte[] byteArr = new byte[1024];
try {
// 读取客户端发送的数据
InputStream inputStream = socket.getInputStream();
int length = 0;
// 客户端没有数据,read阻塞
// while( ( length = inputStream.read(byteArr))!= -1) {
// System.out.println(new String(byteArr, 0, length));
// }
while(true) {
System.out.printf("线程id[%s],等待客户端[%d]发送数据\n", Thread.currentThread().getId(), order);
length = inputStream.read(byteArr);
if (length == -1) break;
System.out.printf("线程id[%s],客户端[%d]:" + new String(byteArr, 0, length) + "\n", Thread.currentThread().getId(), order);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭与客户端的连接
try {
socket.close();
System.out.printf("关闭与客户端[%d]的连接\n", order);
} catch (IOException e) {
}
}
}
}
2)客户端 :采用 win10的命令行 telnet 进程;
- 命令行录入 telnet 127.0.0.1 6666
- 录入 ctrl + ] 进入telnet命令行界面
- send hello100 就把hello100 发送给服务器
发送过程如下:
【小结】
- 显然,在BIO-阻塞式IO模式下,服务器的一个线程处理一个客户端请求;且存在阻塞情况,在客户端数量过多的情况下,性能不高(因为客户端一直挂起,则过多的服务器线程会一直阻塞,浪费大量cpu和内存资源);
- serverSocket.accept() 在没有客户端请求时,会阻塞;
- inputStream.read(...) 在客户端没有发送数据时,会阻塞;