多线程
- 原理:为每个客户端连接分配一个独立的线程来处理。这样多个客户端的请求可以并行处理,避免一个连接的处理阻塞其他连接。
- 具体实现方式:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class MultiThreadedServer {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(12345)) {
while (true) {
Socket clientSocket = serverSocket.accept();
new Thread(new ClientHandler(clientSocket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
static class ClientHandler implements Runnable {
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) {
System.out.println("Received: " + inputLine);
out.println("Echo: " + inputLine);
if ("quit".equals(inputLine)) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
线程池
- 原理:预先创建一组线程,这些线程可以被重复使用来处理客户端请求。避免了频繁创建和销毁线程带来的开销,提高了系统资源的利用率。
- 具体实现方式:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolServer {
private static final ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(12345)) {
while (true) {
Socket clientSocket = serverSocket.accept();
executor.submit(new ClientHandler(clientSocket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
static class ClientHandler implements Runnable {
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) {
System.out.println("Received: " + inputLine);
out.println("Echo: " + inputLine);
if ("quit".equals(inputLine)) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
NIO(New I/O)
- 原理:NIO采用基于通道(Channel)和缓冲区(Buffer)的I/O操作方式,使用多路复用器(Selector)来管理多个通道。它是非阻塞I/O,允许一个线程管理多个连接,大大提高了并发处理能力。
- 具体实现方式:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;
public class NIOServer {
public static void main(String[] args) {
try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
Selector selector = Selector.open()) {
serverSocketChannel.bind(new InetSocketAddress(12345));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int bytesRead = sc.read(byteBuffer);
if (bytesRead > 0) {
byteBuffer.flip();
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(byteBuffer);
System.out.println("Received: " + charBuffer.toString());
ByteBuffer responseBuffer = StandardCharsets.UTF_8.encode("Echo: " + charBuffer.toString());
sc.write(responseBuffer);
} else if (bytesRead == -1) {
sc.close();
}
}
keyIterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}