Java网络IO-BIO

发布时间 2023-12-20 18:25:39作者: yzl1990

Java BIO 就是传统的 Java I/O 编程
BIO(BlockingI/O):同步阻塞,服务器实现:一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理。
单线程情况下,只有一个线程可以处理客户端请求,也就是同时只能连接一个客户端。

优化点:可以通过线程池机制改善,实现多个客户端连接

BIO 方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4 以前的唯一选择,程序简单易理解。

示例:使用 Blocking IO 模型实现一个单线程网络服务器

package com.fixbugs.bio;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Blocking Server
 *
 * @author fix-bugs
 * @date 2023/12/20 17:06
 */
public class BlockingServer {

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(1234);
        while (true) {
            System.out.println("等待客户端连接...");
            Socket clientSocket = server.accept();
            System.out.println("新客户端已连接。当前线程ID:" + Thread.currentThread().getId() + ",线程名称:" + Thread.currentThread().getName());
            byte[] bytes = new byte[1024];
            try(InputStream inputStream = clientSocket.getInputStream();) {
                while (true) {
                    int read = inputStream.read(bytes);
                    if (read != -1) {
                        System.out.println("客户端请求数据:" + new String(bytes, 0, read));
                    } else {
                        break;
                    }
                }
            } finally {
                System.out.println("关闭客户端。当前线程ID:" + Thread.currentThread().getId() + ",线程名称:" + Thread.currentThread().getName());
                clientSocket.close();
            }
        }
    }
}

输出结果:

等待客户端连接...
新客户端已连接。当前线程ID:1,线程名称:main
客户端请求数据:a
客户端请求数据:b
客户端请求数据:c
客户端请求数据:d
客户端请求数据:d
客户端请求数据:s
客户端请求数据:s
客户端请求数据:1
客户端请求数据:2
关闭客户端。当前线程ID:1,线程名称:main
等待客户端连接...

image

问题分析:
每个请求都需要创建独立的线程,与对应的客户端进行业务处理,当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。
连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 accept 操作上,造成线程资源浪费。