使用Java多线程实现简单服务器端处理多客户端连接
- 创建ServerSocket:通过
ServerSocket
类来监听指定端口,等待客户端连接。例如:
ServerSocket serverSocket = new ServerSocket(12345);
- 接受客户端连接并启动新线程处理:在一个循环中,调用
serverSocket.accept()
方法来接受客户端连接。每当有新的连接到来,创建一个新的线程来处理该客户端的请求。示例代码如下:
while (true) {
Socket clientSocket = serverSocket.accept();
new Thread(() -> {
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("Server received: " + inputLine);
if ("exit".equals(inputLine)) {
break;
}
}
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
处理线程安全问题
- 共享资源同步:如果多个线程需要访问共享资源(如共享的数据库连接池、全局计数器等),使用
synchronized
关键字来同步访问。例如:
private static int counter = 0;
public static synchronized void incrementCounter() {
counter++;
}
- 使用线程安全的集合类:在多线程环境下,避免使用非线程安全的集合类,如
ArrayList
、HashMap
。应使用线程安全的替代类,如CopyOnWriteArrayList
、ConcurrentHashMap
。例如:
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
- 锁的粒度控制:尽量减小锁的粒度,只对需要同步的关键代码块加锁,以提高并发性能。例如:
private final Object lock = new Object();
public void someMethod() {
// 非关键代码
synchronized (lock) {
// 关键代码,需要同步
}
// 非关键代码
}
- 使用线程局部变量:对于每个线程都需要独立的变量,可以使用
ThreadLocal
类。例如:
private static ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0);
public void someMethod() {
int value = threadLocalValue.get();
value++;
threadLocalValue.set(value);
}