【Java网络编程】非阻塞IO存在的问题

92 阅读2分钟

在介绍非阻塞IO存在的问题之前,先来写一个阻塞IO通信的demo。

服务器端代码:

@Slf4j
public class Demo1Server {

    public static void main(String[] args) throws IOException {
        // 创建服务器Socket,监听指定端口
        ServerSocket serverSocket = new ServerSocket(8888);

        log.info("Server started. Waiting for client connection...");

        // 等待客户端连接
        Socket socket = serverSocket.accept();
        log.info("Client connected.");

        // 获取输入流和输出流
        InputStream inputStream = socket.getInputStream();
        OutputStream outputStream = socket.getOutputStream();

        // 读取客户端发送的数据
        byte[] buffer = new byte[1024];
        int bytesRead = inputStream.read(buffer);
        String requestData = new String(buffer, 0, bytesRead);
        log.info("Received data from client: " + requestData);

        // 向客户端发送响应数据
        String responseData = "Hello from server!";
        outputStream.write(responseData.getBytes());
        outputStream.flush();

        log.info("Response sent to client.");

        // 关闭连接
        socket.close();
        serverSocket.close();
    }
}

客户端代码:

@Slf4j
public class Demo1Client {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket,指定服务器地址和端口
        Socket socket = new Socket("localhost", 8888);

        // 获取输入流和输出流
        InputStream inputStream = socket.getInputStream();
        OutputStream outputStream = socket.getOutputStream();

        // 向服务器发送数据
        String requestData = "Hello from client!";
        outputStream.write(requestData.getBytes());
        outputStream.flush();
        log.info("Request sent to server.");

        // 读取服务器响应数据
        byte[] buffer = new byte[1024];
        int bytesRead = inputStream.read(buffer);
        String responseData = new String(buffer, 0, bytesRead);
        log.info("Received response from server: " + responseData);

        // 关闭连接
        socket.close();
    }
}

上述代码演示的是客户端与服务器端的一次通信,如果服务端要不断的接收不同客户端的请求,那么服务端的代码需要修改为循环accept,并且需要使用多线程的方式,不然服务端只能处理完一个请求再去处理下一个请求。

如果我们将代码编写为以多线程的方式处理请求,每次来一个新的请求都创建一个线程去处理,这样会导致一个问题:内存资源迟早耗尽。有没有办法可以解决这个问题呢?有的,那就是线程池。

不过引入线程池只是解决了内存耗尽的问题,但这里还存在一个问题:如果一个线程在处理请求的过程中由于其他的IO事件或计算事件导致阻塞,那么该线程也无法处理其他请求,这样的话,就没有充分利用系统资源。而一旦大量的线程碰到这种阻塞,那么系统的整体性能也会受到很大的影响。

为了解决上述问题,NIO就应运而生了。