以下是一个完整的 OnlineUsers
类实现,包含线程安全的在线用户管理功能:
java
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 在线用户管理器(线程安全)
* 功能:
* 1. 用户登录/下线状态管理
* 2. 重复登录强制下线
* 3. 在线用户查询
* 4. 实时消息推送支持
*/
public class OnlineUsers {
// 存储 <用户ID, 客户端连接处理器>
private static final ConcurrentHashMap<Long, ClientHandler> onlineUsers = new ConcurrentHashMap<>();
// 防止实例化
private OnlineUsers() {}
/**
* 添加在线用户(如果已登录会强制下线旧连接)
* @param userId 用户ID
* @param handler 客户端处理器
*/
public static void addUser(Long userId, ClientHandler handler) {
synchronized (onlineUsers) {
// 处理重复登录
ClientHandler existingHandler = onlineUsers.get(userId);
if (existingHandler != null) {
forceDisconnect(existingHandler);
}
onlineUsers.put(userId, handler);
}
}
/**
* 移除在线用户
* @param userId 用户ID
*/
public static void removeUser(Long userId) {
onlineUsers.remove(userId);
}
/**
* 检查用户是否在线
* @param userId 用户ID
* @return 是否在线
*/
public static boolean isUserOnline(Long userId) {
return onlineUsers.containsKey(userId);
}
/**
* 获取在线用户ID列表
* @return 不可修改的ID集合
*/
public static Set<Long> getOnlineUserIds() {
return Collections.unmodifiableSet(onlineUsers.keySet());
}
/**
* 获取在线用户详细信息列表
* @return 用户信息列表(按登录时间排序)
*/
public static List<User> getOnlineUsers() {
return onlineUsers.values().stream()
.filter(handler -> handler.getUser() != null)
.map(ClientHandler::getUser)
.sorted(Comparator.comparing(User::getLoginTime))
.collect(Collectors.toList());
}
/**
* 获取用户连接处理器
* @param userId 用户ID
* @return 处理器实例(可能为null)
*/
public static ClientHandler getHandler(Long userId) {
return onlineUsers.get(userId);
}
/**
* 获取当前在线人数
* @return 在线用户数量
*/
public static int getOnlineCount() {
return onlineUsers.size();
}
/**
* 强制下线用户
* @param userId 用户ID
*/
public static void forceDisconnect(Long userId) {
ClientHandler handler = onlineUsers.get(userId);
if (handler != null) {
forceDisconnect(handler);
removeUser(userId);
}
}
// 内部断开连接方法
private static void forceDisconnect(ClientHandler handler) {
try {
handler.forceDisconnect();
System.out.println("强制断开用户连接: " + handler.getUser().getId());
} catch (Exception e) {
System.err.println("强制断开连接失败: " + e.getMessage());
}
}
/**
* 清除所有在线用户(测试用)
*/
static void clearAll() {
onlineUsers.values().forEach(OnlineUsers::forceDisconnect);
onlineUsers.clear();
}
}
需要配合的 ClientHandler 部分修改:
java
public class ClientHandler implements Runnable {
private User loggedInUser;
// 获取关联的用户信息
public User getUser() {
return loggedInUser;
}
// 强制断开连接
public void forceDisconnect() {
try {
if (!clientsocket.isClosed()) {
clientsocket.close();
}
} catch (IOException e) {
System.err.println("强制断开连接异常: " + e.getMessage());
}
}
// 在登录成功后调用
private void handleSuccessfulLogin(User user) {
this.loggedInUser = user;
OnlineUsers.addUser(user.getId(), this);
}
}
User 类需要扩展的字段:
java
public class User {
private Long id;
private String username;
private Date loginTime; // 登录时间
// Getters/Setters...
}
主要功能说明
方法 | 功能说明 |
---|---|
**addUser()** |
添加在线用户,自动处理重复登录 |
**removeUser()** |
移除指定在线用户 |
**isUserOnline()** |
检查指定用户是否在线 |
**getOnlineUserIds()** |
获取所有在线用户ID(不可修改集合) |
**getOnlineUsers()** |
获取详细在线用户列表(按登录时间排序) |
**getHandler()** |
获取用户连接处理器(用于消息推送) |
**getOnlineCount()** |
获取当前在线人数 |
**forceDisconnect()** |
强制断开指定用户连接 |
**clearAll()** |
清空所有在线用户(测试用) |
使用示例
java
// 用户登录成功
User user = new User(123L, "张三");
ClientHandler handler = new ClientHandler(socket);
OnlineUsers.addUser(user.getId(), handler);
// 检查用户状态
boolean isOnline = OnlineUsers.isUserOnline(123L);
// 发送实时消息
ClientHandler targetHandler = OnlineUsers.getHandler(456L);
if (targetHandler != null) {
targetHandler.sendMessage(new ChatMessage(...));
}
// 获取在线用户统计
System.out.println("当前在线人数: " + OnlineUsers.getOnlineCount());
设计特点
- 线程安全:使用
**ConcurrentHashMap**
和同步块保证线程安全 - 自动清理:连接断开时自动移除用户(需在
**ClientHandler**
的 finally 块调用**removeUser()**
) - 强制下线:处理重复登录时自动断开旧连接
- 可扩展性:支持按需获取用户ID列表或详细用户信息
- 状态跟踪:记录用户登录时间用于排序和分析
建议配合心跳检测机制(如每30秒检测一次连接活性)来维护在线状态的准确性。