




本文介绍如何基于 java 原生 socket 构建高并发、非阻塞的服务器,通过合理线程模型、异步回调与资源隔离机制,解决外部库调用导致的不确定等待问题,并确保多客户端请求间互不干扰。
在多客户端并发访问的服务器场景中,直接使用 while(true) 阻塞式轮询 + 每请求新建线程(尤其是嵌套线程)极易引发资源耗尽、线程泄漏、响应丢失及竞态问题。核心矛盾在于:外部库的 workonRequest() 是同步阻塞调用,但服务器必须支持高并发、低延迟、可伸缩的 I/O 处理。下面提供一套兼顾兼容性与健壮性的实践方案。
避免无限嵌套线程,改用固定大小的线程池执行耗时操作,并通过唯一标识符(如 request ID 或 socket channel)关联请求与响应:
public class MyServer {
private final ExecutorService workerPool = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors() * 2
);
private final ServerSocket server;
public MyServer(int port) throws IOException {
this.server = new ServerSocket(port);
}
public void listenRequest() {

new Thread(() -> {
System.out.println("Server listening on port " + server.getLocalPort());
while (!Thread.currentThread().isInterrupted()) {
try (Socket socket = server.accept()) {
// 为每个连接分配独立的 I/O 流,避免跨请求复用
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
socket.setTcpNoDelay(true); // 启用 Nagle 算法禁用,降低小包延迟
// 提交至线程池异步处理,主线程立即返回继续 accept
workerPool.submit(() -> handleRequest(input, output, socket));
} catch (IOException e) {
if (!server.isClosed()) {
System.err.println("Accept error: " + e.getMessage());
}
}
}
}, "Acceptor-Thread").start();
}
private void handleRequest(ObjectInputStream input, ObjectOutputStream output, Socket socket) {
try {
while (!socket.isClosed() && socket.isConnected()) {
// 1. 读取请求(建议添加超时)
socket.setSoTimeout(30_000); // 30秒读超时
Object request = input.readObject();
// 2. 异步调用外部库(关键:不阻塞当前线程)
CompletableFuture不要“为每个请求开一个线程再开一个线程”,而应“为每个连接分配专属 I/O 流,由统一受控线程池执行业务逻辑”。通过 CompletableFuture 封装外部库调用、显式超时控制、连接级资源隔离,即可在不引入 Spring/Quarkus 等框架的前提下,构建出线程安全、可监控、可伸缩的并发服务器。