实时在线状态
以下是一个完整的 OnlineUsers
类实现,包含线程安全的在线用户管理功能:
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 部分修改:
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 类需要扩展的字段:
public class User {private Long id;private String username;private Date loginTime; // 登录时间// Getters/Setters...
}
主要功能说明
方法 | 功能说明 |
---|---|
**addUser()** | 添加在线用户,自动处理重复登录 |
**removeUser()** | 移除指定在线用户 |
**isUserOnline()** | 检查指定用户是否在线 |
**getOnlineUserIds()** | 获取所有在线用户ID(不可修改集合) |
**getOnlineUsers()** | 获取详细在线用户列表(按登录时间排序) |
**getHandler()** | 获取用户连接处理器(用于消息推送) |
**getOnlineCount()** | 获取当前在线人数 |
**forceDisconnect()** | 强制断开指定用户连接 |
**clearAll()** | 清空所有在线用户(测试用) |
使用示例
// 用户登录成功
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秒检测一次连接活性)来维护在线状态的准确性。