面试题答案
一键面试设计思路
- 异常分类:通过捕获不同类型的
IOException
及其子类,对异常进行分类。例如,SocketTimeoutException
表示连接超时,EOFException
表示流结束等。 - 日志记录:使用日志框架(如
log4j
或java.util.logging
)对不同类型的异常进行记录,记录的信息应包含异常类型、发生时间、相关连接信息等。 - 连接关闭:对于严重异常(如
SocketException
中表示连接已断开的情况),需要优雅地关闭相关连接。为了减少对其他正常连接的影响,每个连接应该在独立的线程中处理,这样一个连接的异常不会影响其他线程处理的连接。
关键代码片段
- 日志配置(以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
- 异常处理代码:
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);
}
}
}
- 服务器端代码:
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异常,通过异常分类记录日志并优雅关闭连接。实际应用中,可根据业务需求进一步完善日志记录和异常处理逻辑。