上一篇文章 3分钟了解linux网络IO模型 聊到了linux的五种IO模型,这篇文章将讲解一下Java的BIO模式。
BIO (阻塞IO)
传统BIO模型
Java在1.4版本以前,只有BIO。Java的BIO,客户端通过Socket来连接服务端的地址与端口。服务端采用ServerSocket启用一个独立Accept线程监听客户端发起的连接,客户端的连接数与服务器的处理线程数为1:1的关系,一旦客户端的连接数过多,Java不断创建线程去处理新的连接,有可能导致OOM
客户端代码:
Socket socket = new Socket();
/*连接服务器*/
socket.connect(new InetSocketAddress("127.0.0.1",8080));
//与服务器通信的输入流与输出流
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input =new ObjectInputStream(socket.getInputStream());
/*向服务器输出请求*/
output.writeUTF("this msg from client");
output.flush();
//接收服务器的输出
System.out.println(input.readUTF());
服务端代码:
ServerSocket serverSocket = new ServerSocket();
/*绑定监听端口*/
serverSocket.bind(new InetSocketAddress(8080));
Socket socket;
while(true){
//监听客户端连接
socket=serverSocket.accept();
//新启用线程处理客户端连接
new Thread(new ServerTask(socket)).start();
}
伪异步IO流
针对上面的客户端连接数过多,导致Jvm发生OOM的现象,我们对服务端的代码进行了改进,增加线程池对创建线程进行管理。但是这种办法仍然有缺点,因为线程池限制了线程的数量,如果发生线程读取非常缓慢(数据量大、网速慢),在高并发下,大量其他线程只能在队列中等待。
服务端代码
//服务端启动必备
ServerSocket serverSocket = new ServerSocket();
//表示服务端在哪个端口上监听
serverSocket.bind(new InetSocketAddress(8080));
Socket socket;
while (true) {
socket = serverSocket.accept();
//线程池来处理线程创建
executorService.execute(new ServerTask(socket));
}