MST

星途 面试题库

面试题:Java BIO异常处理之复杂场景优化

在一个高并发的Java BIO服务器应用中,多个客户端连接可能同时产生各种I/O异常。请设计一个异常处理框架,能够区分不同类型的异常,对不同异常进行分类记录日志,并且在某些严重异常发生时能够优雅地关闭相关连接,同时尽可能减少对其他正常连接的影响。请阐述设计思路并给出关键代码片段。
30.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 异常分类:通过捕获不同类型的IOException及其子类,对异常进行分类。例如,SocketTimeoutException表示连接超时,EOFException表示流结束等。
  2. 日志记录:使用日志框架(如log4jjava.util.logging)对不同类型的异常进行记录,记录的信息应包含异常类型、发生时间、相关连接信息等。
  3. 连接关闭:对于严重异常(如SocketException中表示连接已断开的情况),需要优雅地关闭相关连接。为了减少对其他正常连接的影响,每个连接应该在独立的线程中处理,这样一个连接的异常不会影响其他线程处理的连接。

关键代码片段

  1. 日志配置(以log4j为例)
    • src/main/resources目录下创建log4j.properties文件:
log4j.rootLogger=info,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
  1. 异常处理代码
import org.apache.log4j.Logger;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientHandler implements Runnable {
    private static final Logger logger = Logger.getLogger(ClientHandler.class);
    private final Socket clientSocket;

    public ClientHandler(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
             PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                // 处理客户端输入
                out.println("Echo: " + inputLine);
            }
        } catch (SocketTimeoutException e) {
            logger.warn("Socket timeout for connection " + clientSocket, e);
        } catch (EOFException e) {
            logger.info("End of stream reached for connection " + clientSocket, e);
        } catch (SocketException e) {
            if ("Socket closed".equals(e.getMessage())) {
                logger.info("Socket closed for connection " + clientSocket, e);
            } else {
                logger.error("Serious socket error for connection " + clientSocket, e);
                closeConnectionGracefully();
            }
        } catch (IOException e) {
            logger.error("General I/O error for connection " + clientSocket, e);
            closeConnectionGracefully();
        }
    }

    private void closeConnectionGracefully() {
        try {
            if (clientSocket != null &&!clientSocket.isClosed()) {
                clientSocket.close();
            }
        } catch (IOException e) {
            logger.error("Error closing socket", e);
        }
    }
}
  1. 服务器端代码
import org.apache.log4j.PropertyConfigurator;

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

public class BioServer {
    private static final int PORT = 12345;

    public static void main(String[] args) {
        PropertyConfigurator.configure("src/main/resources/log4j.properties");
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            while (true) {
                Socket clientSocket = serverSocket.accept();
                new Thread(new ClientHandler(clientSocket)).start();
            }
        } catch (IOException e) {
            logger.error("Server startup error", e);
        }
    }
}

以上代码展示了如何在Java BIO服务器中处理高并发下的I/O异常,通过异常分类记录日志并优雅关闭连接。实际应用中,可根据业务需求进一步完善日志记录和异常处理逻辑。