长麻添加清理的资源相关代码
parent
e72506ed2e
commit
f9bae0eff6
|
|
@ -12,6 +12,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import robot.mj.info.RobotUser;
|
import robot.mj.info.RobotUser;
|
||||||
|
import robot.mj.thread.ThreadPoolConfig;
|
||||||
import taurus.client.TaurusClient;
|
import taurus.client.TaurusClient;
|
||||||
import taurus.client.business.GroupRoomBusiness;
|
import taurus.client.business.GroupRoomBusiness;
|
||||||
import taurus.util.ROBOTEventType;
|
import taurus.util.ROBOTEventType;
|
||||||
|
|
@ -37,6 +38,12 @@ public class EXGameController extends GameController {
|
||||||
//机器人房间
|
//机器人房间
|
||||||
protected static final Map<String, RobotUser> robotRoomMapping = new ConcurrentHashMap<>();
|
protected static final Map<String, RobotUser> robotRoomMapping = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
//记录最近访问时间
|
||||||
|
private static final Map<String, Long> lastAccessTime = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
//设置连接超时时间(5分钟)
|
||||||
|
private static final long CONNECTION_TIMEOUT = 5 * 60 * 1000;
|
||||||
|
|
||||||
public EXGameController() {
|
public EXGameController() {
|
||||||
super();
|
super();
|
||||||
log.info("长沙麻将游戏控制器已初始化");
|
log.info("长沙麻将游戏控制器已初始化");
|
||||||
|
|
@ -396,7 +403,7 @@ public class EXGameController extends GameController {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("机器人加入房间超时", e);
|
log.error("机器人加入房间超时", e);
|
||||||
}
|
}
|
||||||
});
|
}, ThreadPoolConfig.getBusinessThreadPool());//指定自定义线程池
|
||||||
robotUser.setIntoRoomTime(robotConnectionManager.getTime());
|
robotUser.setIntoRoomTime(robotConnectionManager.getTime());
|
||||||
System.err.println("已进入房间准备成功: " + robotUser.getConnecId());
|
System.err.println("已进入房间准备成功: " + robotUser.getConnecId());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -444,7 +451,51 @@ public class EXGameController extends GameController {
|
||||||
* 根据机器人ID删除其所在的房间信息
|
* 根据机器人ID删除其所在的房间信息
|
||||||
*/
|
*/
|
||||||
public static void removeRobotRoomInfo(String robotId) {
|
public static void removeRobotRoomInfo(String robotId) {
|
||||||
robotRoomMapping.remove(robotId);
|
RobotUser removedUser = robotRoomMapping.remove(robotId);
|
||||||
|
lastAccessTime.remove(robotId);
|
||||||
|
|
||||||
|
// 如果有连接ID,也一并清理
|
||||||
|
if (removedUser != null && removedUser.getConnecId() != null) {
|
||||||
|
robotRoomMapping.remove(removedUser.getConnecId());
|
||||||
|
lastAccessTime.remove(removedUser.getConnecId());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("清理机器人房间信息: " + robotId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新连接的最后访问时间
|
||||||
|
*/
|
||||||
|
public static void updateLastAccessTime(String connecId) {
|
||||||
|
lastAccessTime.put(connecId, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理超时的连接
|
||||||
|
*/
|
||||||
|
public static void cleanupExpiredConnections() {
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
List<String> expiredConnections = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Map.Entry<String, Long> entry : lastAccessTime.entrySet()) {
|
||||||
|
if (currentTime - entry.getValue() > CONNECTION_TIMEOUT) {
|
||||||
|
expiredConnections.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String connecId : expiredConnections) {
|
||||||
|
RobotUser robotUser = robotRoomMapping.get(connecId);
|
||||||
|
if (robotUser != null) {
|
||||||
|
System.out.println("清理超时连接: " + connecId + ", 机器人ID: " + robotUser.getRobotId());
|
||||||
|
robotConnectionManager.disconnectFromGameServer(connecId);
|
||||||
|
}
|
||||||
|
robotRoomMapping.remove(connecId);
|
||||||
|
lastAccessTime.remove(connecId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expiredConnections.isEmpty()) {
|
||||||
|
System.out.println("本次清理了 " + expiredConnections.size() + " 个超时连接");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import robot.mj.info.RobotUser;
|
import robot.mj.info.RobotUser;
|
||||||
|
import robot.mj.thread.ResourceCleanupUtil;
|
||||||
|
import robot.mj.thread.ThreadPoolConfig;
|
||||||
import taurus.client.NetManager;
|
import taurus.client.NetManager;
|
||||||
|
|
||||||
import static robot.mj.EXGameController.robotRoomMapping;
|
import static robot.mj.EXGameController.robotRoomMapping;
|
||||||
|
|
@ -52,7 +54,10 @@ public class EXMainServer extends MainServer{
|
||||||
// 1. 先启动独立的事件处理线程(只启动一次)
|
// 1. 先启动独立的事件处理线程(只启动一次)
|
||||||
startNetEventThread();
|
startNetEventThread();
|
||||||
|
|
||||||
// 2. 启动连接检查定时任务
|
// 2. 启动资源清理定时任务
|
||||||
|
startResourceCleanupScheduler();
|
||||||
|
|
||||||
|
// 3. 启动系统监控
|
||||||
//startConnectionCheckScheduler();
|
//startConnectionCheckScheduler();
|
||||||
//测试
|
//测试
|
||||||
Jedis jedis2 = Redis.use("group1_db2").getJedis();
|
Jedis jedis2 = Redis.use("group1_db2").getJedis();
|
||||||
|
|
@ -83,6 +88,7 @@ public class EXMainServer extends MainServer{
|
||||||
|
|
||||||
log.info("长沙麻将机器人服务器已启动");
|
log.info("长沙麻将机器人服务器已启动");
|
||||||
log.info("服务器将监听端口 {} 用于接收robot_mgr管理协议", gameSetting.port);
|
log.info("服务器将监听端口 {} 用于接收robot_mgr管理协议", gameSetting.port);
|
||||||
|
System.out.println("当前线程池配置: " + ThreadPoolConfig.getThreadPoolStatus());
|
||||||
|
|
||||||
jedis2.close();
|
jedis2.close();
|
||||||
}
|
}
|
||||||
|
|
@ -107,6 +113,36 @@ public class EXMainServer extends MainServer{
|
||||||
eventThread.start();
|
eventThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动资源清理定时任务
|
||||||
|
*/
|
||||||
|
private void startResourceCleanupScheduler() {
|
||||||
|
Thread cleanupThread = new Thread(() -> {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
//每30秒执行一次资源清理
|
||||||
|
Thread.sleep(30000);
|
||||||
|
ResourceCleanupUtil.performCleanup();
|
||||||
|
System.out.println("线程池状态: " + ThreadPoolConfig.getThreadPoolStatus());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("资源清理任务异常: " + e.getMessage());
|
||||||
|
// 发生异常时尝试清理
|
||||||
|
try {
|
||||||
|
ResourceCleanupUtil.performCleanup();
|
||||||
|
} catch (Exception cleanupEx) {
|
||||||
|
System.err.println("异常清理也失败: " + cleanupEx.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "ResourceCleanupThread");
|
||||||
|
|
||||||
|
cleanupThread.setDaemon(true);
|
||||||
|
cleanupThread.start();
|
||||||
|
System.out.println("资源清理定时任务已启动");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,7 @@ import taurus.util.ROBOTEventType;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import static robot.mj.thread.ThreadPoolConfig.getBusinessThreadPool;
|
|
||||||
import static robot.mj.thread.ThreadPoolConfig.scheduleDelay;
|
import static robot.mj.thread.ThreadPoolConfig.scheduleDelay;
|
||||||
|
|
||||||
import static robot.mj.EXGameController.robotRoomMapping;
|
import static robot.mj.EXGameController.robotRoomMapping;
|
||||||
|
|
@ -37,6 +35,15 @@ public class RobotConnectionManager {
|
||||||
|
|
||||||
private Logger log = Logger.getLogger(RobotConnectionManager.class);
|
private Logger log = Logger.getLogger(RobotConnectionManager.class);
|
||||||
private static final Map<String, HuNanChangSha> huNanChangShaInstances = new ConcurrentHashMap<>();
|
private static final Map<String, HuNanChangSha> huNanChangShaInstances = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
//记录活跃连接 用于资源清理判断
|
||||||
|
private static final Set<String> activeConnections = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
|
//记录连接创建时间
|
||||||
|
private static final Map<String, Long> connectionCreationTime = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
//连接最大生存时间(5分钟)
|
||||||
|
private static final long MAX_CONNECTION_LIFETIME = 5 * 60 * 1000;
|
||||||
private final EXGameController exGameController;
|
private final EXGameController exGameController;
|
||||||
|
|
||||||
private final String host= Config.GAME_SERVER_HOST;
|
private final String host= Config.GAME_SERVER_HOST;
|
||||||
|
|
@ -79,6 +86,13 @@ public class RobotConnectionManager {
|
||||||
* 获取长沙麻将处理器实例
|
* 获取长沙麻将处理器实例
|
||||||
*/
|
*/
|
||||||
private HuNanChangSha getHuNanChangShaInstance(String connecId) {
|
private HuNanChangSha getHuNanChangShaInstance(String connecId) {
|
||||||
|
//标记连接为活跃状态
|
||||||
|
activeConnections.add(connecId);
|
||||||
|
connectionCreationTime.put(connecId, System.currentTimeMillis());
|
||||||
|
|
||||||
|
//定期清理过期连接
|
||||||
|
cleanupExpiredInstances();
|
||||||
|
|
||||||
HuNanChangSha existingInstance = huNanChangShaInstances.get(connecId);
|
HuNanChangSha existingInstance = huNanChangShaInstances.get(connecId);
|
||||||
if (existingInstance != null) {
|
if (existingInstance != null) {
|
||||||
return existingInstance;
|
return existingInstance;
|
||||||
|
|
@ -135,12 +149,17 @@ public class RobotConnectionManager {
|
||||||
System.out.println("开始主动断开连接: {"+connecId+"}");
|
System.out.println("开始主动断开连接: {"+connecId+"}");
|
||||||
RobotUser robotUser = robotRoomMapping.remove(connecId);
|
RobotUser robotUser = robotRoomMapping.remove(connecId);
|
||||||
|
|
||||||
|
//标记连接为非活跃
|
||||||
|
activeConnections.remove(connecId);
|
||||||
|
connectionCreationTime.remove(connecId);
|
||||||
|
|
||||||
//清理连接数据
|
//清理连接数据
|
||||||
if (connecId != null) {
|
if (connecId != null) {
|
||||||
HuNanChangSha.removeFromRedis(connecId);
|
HuNanChangSha.removeFromRedis(connecId);
|
||||||
|
|
||||||
HuNanChangSha instance = huNanChangShaInstances.get(connecId);
|
HuNanChangSha instance = huNanChangShaInstances.get(connecId);
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
|
//清理所有集合数据以释放内存
|
||||||
instance.getChangShaCardInhand().clear();
|
instance.getChangShaCardInhand().clear();
|
||||||
instance.getChuGuoCardInhand().clear();
|
instance.getChuGuoCardInhand().clear();
|
||||||
instance.getgangdepai().clear();
|
instance.getgangdepai().clear();
|
||||||
|
|
@ -151,12 +170,15 @@ public class RobotConnectionManager {
|
||||||
System.out.println("清空HuNanChangSha集合数据: " + connecId);
|
System.out.println("清空HuNanChangSha集合数据: " + connecId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//移除实例和相关数据
|
||||||
huNanChangShaInstances.remove(connecId);
|
huNanChangShaInstances.remove(connecId);
|
||||||
playerOutcardsMapByConn.remove(connecId);
|
playerOutcardsMapByConn.remove(connecId);
|
||||||
playerchisMapByConn.remove(connecId);
|
playerchisMapByConn.remove(connecId);
|
||||||
playerpengsMapByConn.remove(connecId);
|
playerpengsMapByConn.remove(connecId);
|
||||||
playermingsMapByConn.remove(connecId);
|
playermingsMapByConn.remove(connecId);
|
||||||
playerzisMapByConn.remove(connecId);
|
playerzisMapByConn.remove(connecId);
|
||||||
|
|
||||||
|
System.out.println("清理完成,当前活跃连接数: " + activeConnections.size() + ", 实例数: " + huNanChangShaInstances.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (robotUser != null) {
|
if (robotUser != null) {
|
||||||
|
|
@ -173,6 +195,34 @@ public class RobotConnectionManager {
|
||||||
} else {
|
} else {
|
||||||
System.out.println("客户端连接不存在: {"+connecId+"}");
|
System.out.println("客户端连接不存在: {"+connecId+"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//同时清理机器人房间映射
|
||||||
|
EXGameController.removeRobotRoomInfo(robotUser.getRobotId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理过期的实例
|
||||||
|
*/
|
||||||
|
private void cleanupExpiredInstances() {
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
List<String> expiredConnections = new ArrayList<>();
|
||||||
|
|
||||||
|
//检查连接生存时间
|
||||||
|
for (Map.Entry<String, Long> entry : connectionCreationTime.entrySet()) {
|
||||||
|
if (currentTime - entry.getValue() > MAX_CONNECTION_LIFETIME) {
|
||||||
|
expiredConnections.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//清理过期连接
|
||||||
|
for (String connecId : expiredConnections) {
|
||||||
|
System.out.println("清理过期连接实例: " + connecId);
|
||||||
|
disconnectFromGameServer(connecId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expiredConnections.isEmpty()) {
|
||||||
|
System.out.println("本次清理了 " + expiredConnections.size() + " 个过期连接实例");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,6 +391,15 @@ public class RobotConnectionManager {
|
||||||
*/
|
*/
|
||||||
private void handleProtocol(String command, Message message, TaurusClient client, String connecId) {
|
private void handleProtocol(String command, Message message, TaurusClient client, String connecId) {
|
||||||
RobotUser robotUser = robotRoomMapping.get(connecId);
|
RobotUser robotUser = robotRoomMapping.get(connecId);
|
||||||
|
|
||||||
|
//更新连接的最后访问时间
|
||||||
|
EXGameController.updateLastAccessTime(connecId);
|
||||||
|
|
||||||
|
if (robotUser == null) {
|
||||||
|
System.err.println("未找到机器人用户信息,连接ID: " + connecId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int robotId = Integer.parseInt(robotUser.getRobotId());
|
int robotId = Integer.parseInt(robotUser.getRobotId());
|
||||||
ITObject param = message.param;
|
ITObject param = message.param;
|
||||||
HuNanChangSha huNanChangSha = getHuNanChangShaInstance(connecId);
|
HuNanChangSha huNanChangSha = getHuNanChangShaInstance(connecId);
|
||||||
|
|
@ -598,14 +657,15 @@ public class RobotConnectionManager {
|
||||||
else if ("2009".equalsIgnoreCase(command)) {
|
else if ("2009".equalsIgnoreCase(command)) {
|
||||||
//直接使用定时任务替代Thread.sleep,避免嵌套异步调用
|
//直接使用定时任务替代Thread.sleep,避免嵌套异步调用
|
||||||
scheduleDelay(() -> {
|
scheduleDelay(() -> {
|
||||||
Jedis localJedis = Redis.use().getJedis();
|
Jedis jedis = null;
|
||||||
try {
|
try {
|
||||||
|
jedis = Redis.use().getJedis();
|
||||||
Integer paramRobotId = param.getInt("aid");
|
Integer paramRobotId = param.getInt("aid");
|
||||||
if (robotUser != null) {
|
if (robotUser != null && paramRobotId != null) {
|
||||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||||
|
|
||||||
//查询该房间的玩家信息
|
//查询该房间的玩家信息
|
||||||
String playersStr = localJedis.hget(roomKey, "players");
|
String playersStr = jedis.hget(roomKey, "players");
|
||||||
if (playersStr != null && !playersStr.equals("[]")) {
|
if (playersStr != null && !playersStr.equals("[]")) {
|
||||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||||
String[] playerIds = players.split(",");
|
String[] playerIds = players.split(",");
|
||||||
|
|
@ -614,12 +674,12 @@ public class RobotConnectionManager {
|
||||||
if (playerIds.length == 1) {
|
if (playerIds.length == 1) {
|
||||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||||
if (playerId == paramRobotId) {
|
if (playerId == paramRobotId) {
|
||||||
String gpid = localJedis.hget(roomKey, "gpid");
|
String gpid = jedis.hget(roomKey, "gpid");
|
||||||
|
|
||||||
//更新机器人剩余数量
|
//更新机器人剩余数量
|
||||||
if (count != null && count.containsKey(Integer.parseInt(gpid))) {
|
if (gpid != null && count != null && count.containsKey(Integer.parseInt(gpid))) {
|
||||||
Integer currentValue = count.get(Integer.parseInt(gpid));
|
Integer currentValue = count.get(Integer.parseInt(gpid));
|
||||||
if (currentValue > 0) {
|
if (currentValue != null && currentValue > 0) {
|
||||||
count.put(Integer.parseInt(gpid), currentValue - 1);
|
count.put(Integer.parseInt(gpid), currentValue - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -638,11 +698,15 @@ public class RobotConnectionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
System.err.println("2009协议数字格式异常,robotId: " + param.get("aid") + ", connecId: " + connecId);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
System.err.println("2009协议空指针异常,connecId: " + connecId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("处理机器人房间映射检查时发生异常", e);
|
System.err.println("2009协议处理异常: " + e.getMessage() + ", connecId: " + connecId);
|
||||||
} finally {
|
} finally {
|
||||||
if (localJedis != null) {
|
if (jedis != null) {
|
||||||
localJedis.close();
|
jedis.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 6, TimeUnit.SECONDS);
|
}, 6, TimeUnit.SECONDS);
|
||||||
|
|
@ -650,13 +714,8 @@ public class RobotConnectionManager {
|
||||||
//结算
|
//结算
|
||||||
else if ("817".equalsIgnoreCase(command)) {
|
else if ("817".equalsIgnoreCase(command)) {
|
||||||
//清空所有HuNanChangSha相关的集合数据
|
//清空所有HuNanChangSha相关的集合数据
|
||||||
huNanChangSha.getChangShaCardInhand().clear();
|
huNanChangSha.clearAllData();
|
||||||
huNanChangSha.getChuGuoCardInhand().clear();
|
|
||||||
huNanChangSha.getgangdepai().clear();
|
|
||||||
huNanChangSha.getpongGroup().clear();
|
|
||||||
huNanChangSha.getchowGroup().clear();
|
|
||||||
huNanChangSha.getchangShaCardInhandgang().clear();
|
|
||||||
huNanChangSha.getChuGuoPainum().clear();
|
|
||||||
Integer type = param.getInt("type");
|
Integer type = param.getInt("type");
|
||||||
if (type == 1 || type == 2) { //为1为大结算 为2为解散
|
if (type == 1 || type == 2) { //为1为大结算 为2为解散
|
||||||
if (count != null && count.containsKey(pid)) {
|
if (count != null && count.containsKey(pid)) {
|
||||||
|
|
@ -667,6 +726,9 @@ public class RobotConnectionManager {
|
||||||
}
|
}
|
||||||
//更新机器人剩余数量
|
//更新机器人剩余数量
|
||||||
updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
|
updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
|
||||||
|
|
||||||
|
//游戏结束后主动断开连接
|
||||||
|
disconnectFromGameServer(connecId);
|
||||||
}
|
}
|
||||||
ITObject params = TObject.newInstance();
|
ITObject params = TObject.newInstance();
|
||||||
params.putString("session", client.getSession());
|
params.putString("session", client.getSession());
|
||||||
|
|
@ -778,7 +840,7 @@ public class RobotConnectionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}, ThreadPoolConfig.getBusinessThreadPool()); //指定自定义线程池
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("机器人登录异常");
|
log.error("机器人登录异常");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,21 @@ public class HuNanChangSha {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理所有集合数据
|
||||||
|
*/
|
||||||
|
public void clearAllData() {
|
||||||
|
changShaCardInhand.clear();
|
||||||
|
changShachuguopai.clear();
|
||||||
|
gangdepai.clear();
|
||||||
|
pongGroup.clear();
|
||||||
|
chowGroup.clear();
|
||||||
|
changShaCardInhandgang.clear();
|
||||||
|
chuGuoPainum.clear();
|
||||||
|
|
||||||
|
System.out.println("已清空HuNanChangSha所有集合数据");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 出牌广播协议 812
|
* 出牌广播协议 812
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package robot.mj.thread;
|
||||||
|
|
||||||
|
import robot.mj.EXGameController;
|
||||||
|
import robot.mj.RobotConnectionManager;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源清理工具类
|
||||||
|
* 用于管理和清理不再使用的资源 防止内存泄漏
|
||||||
|
*/
|
||||||
|
public class ResourceCleanupUtil {
|
||||||
|
|
||||||
|
//需要清理的资源
|
||||||
|
private static final Set<String> pendingCleanupResources = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行资源清理
|
||||||
|
* 清理已完成对局但仍在内存中的资源
|
||||||
|
*/
|
||||||
|
public static void performCleanup() {
|
||||||
|
if (pendingCleanupResources.isEmpty()) {
|
||||||
|
//执行常规清理
|
||||||
|
performRegularCleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("开始执行资源清理,待清理资源数: " + pendingCleanupResources.size());
|
||||||
|
int cleanedCount = 0;
|
||||||
|
|
||||||
|
Set<String> resourcesToClean = ConcurrentHashMap.newKeySet();
|
||||||
|
resourcesToClean.addAll(pendingCleanupResources);
|
||||||
|
|
||||||
|
for (String resourceId : resourcesToClean) {
|
||||||
|
try {
|
||||||
|
//这里可以根据resourceId的具体类型执行不同的清理逻辑
|
||||||
|
//暂时保持原有逻辑
|
||||||
|
|
||||||
|
//从待清理列表中移除
|
||||||
|
pendingCleanupResources.remove(resourceId);
|
||||||
|
cleanedCount++;
|
||||||
|
|
||||||
|
System.out.println("已清理资源: " + resourceId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("清理资源时发生异常: " + resourceId + ", 错误: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("资源清理完成,共清理: " + cleanedCount + " 个资源");
|
||||||
|
|
||||||
|
//执行常规清理
|
||||||
|
performRegularCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行常规清理
|
||||||
|
*/
|
||||||
|
private static void performRegularCleanup() {
|
||||||
|
try {
|
||||||
|
//清理过期的机器人连接
|
||||||
|
EXGameController.cleanupExpiredConnections();
|
||||||
|
|
||||||
|
//输出当前系统状态
|
||||||
|
System.out.println("=== 系统资源状态 ===");
|
||||||
|
System.out.println(ThreadPoolConfig.getThreadPoolStatus());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("执行常规清理时发生异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -8,36 +8,36 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
*/
|
*/
|
||||||
public class ThreadPoolConfig {
|
public class ThreadPoolConfig {
|
||||||
|
|
||||||
// 优化后的线程池配置:针对机器人场景优化
|
//线程池配置
|
||||||
private static final ExecutorService BUSINESS_THREAD_POOL =
|
private static final ExecutorService BUSINESS_THREAD_POOL =
|
||||||
new ThreadPoolExecutor(
|
new ThreadPoolExecutor(
|
||||||
10, // 核心线程数 - 减少核心线程数
|
5, //核心线程数
|
||||||
50, // 最大线程数 - 降低最大线程数
|
20, //最大线程数
|
||||||
30, // 空闲线程存活时间 - 缩短存活时间
|
60, //空闲线程存活时间
|
||||||
TimeUnit.SECONDS,
|
TimeUnit.SECONDS,
|
||||||
new LinkedBlockingQueue<>(10000), // 增大队列容量,减少拒绝任务
|
new LinkedBlockingQueue<>(5000),
|
||||||
new ThreadFactory() {
|
new ThreadFactory() {
|
||||||
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||||
@Override
|
@Override
|
||||||
public Thread newThread(Runnable r) {
|
public Thread newThread(Runnable r) {
|
||||||
Thread t = new Thread(r, "RobotBusinessThread-" + threadNumber.getAndIncrement());
|
Thread t = new Thread(r, "RobotBusinessThread-" + threadNumber.getAndIncrement());
|
||||||
t.setDaemon(true);
|
t.setDaemon(true);
|
||||||
t.setPriority(Thread.NORM_PRIORITY - 2); // 进一步降低线程优先级
|
t.setPriority(Thread.NORM_PRIORITY - 1);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:由调用线程执行
|
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||||
);
|
);
|
||||||
|
|
||||||
// 添加定时任务线程池,专门处理延迟操作
|
//添加定时任务线程池
|
||||||
private static final ScheduledExecutorService SCHEDULED_EXECUTOR_SERVICE =
|
private static final ScheduledExecutorService SCHEDULED_EXECUTOR_SERVICE =
|
||||||
Executors.newScheduledThreadPool(4, new ThreadFactory() {
|
new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
|
||||||
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||||
@Override
|
@Override
|
||||||
public Thread newThread(Runnable r) {
|
public Thread newThread(Runnable r) {
|
||||||
Thread t = new Thread(r, "RobotScheduledThread-" + threadNumber.getAndIncrement());
|
Thread t = new Thread(r, "RobotScheduledThread-" + threadNumber.getAndIncrement());
|
||||||
t.setDaemon(true);
|
t.setDaemon(true);
|
||||||
t.setPriority(Thread.NORM_PRIORITY - 2);
|
t.setPriority(Thread.NORM_PRIORITY - 1);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -67,22 +67,16 @@ public class ThreadPoolConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行周期性任务
|
* 关闭线程池 释放资源
|
||||||
*/
|
|
||||||
public static void scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
|
|
||||||
SCHEDULED_EXECUTOR_SERVICE.scheduleAtFixedRate(task, initialDelay, period, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 优雅关闭线程池,释放资源
|
|
||||||
*/
|
*/
|
||||||
public static void shutdown() {
|
public static void shutdown() {
|
||||||
System.out.println("开始关闭线程池...");
|
System.out.println("开始关闭线程池...");
|
||||||
|
|
||||||
// 关闭定时任务线程池
|
//关闭定时任务线程池
|
||||||
SCHEDULED_EXECUTOR_SERVICE.shutdown();
|
SCHEDULED_EXECUTOR_SERVICE.shutdown();
|
||||||
try {
|
try {
|
||||||
if (!SCHEDULED_EXECUTOR_SERVICE.awaitTermination(5, TimeUnit.SECONDS)) {
|
if (!SCHEDULED_EXECUTOR_SERVICE.awaitTermination(3, TimeUnit.SECONDS)) {
|
||||||
|
System.out.println("定时任务线程池强制关闭");
|
||||||
SCHEDULED_EXECUTOR_SERVICE.shutdownNow();
|
SCHEDULED_EXECUTOR_SERVICE.shutdownNow();
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
@ -90,10 +84,11 @@ public class ThreadPoolConfig {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭业务线程池
|
//关闭业务线程池
|
||||||
BUSINESS_THREAD_POOL.shutdown();
|
BUSINESS_THREAD_POOL.shutdown();
|
||||||
try {
|
try {
|
||||||
if (!BUSINESS_THREAD_POOL.awaitTermination(10, TimeUnit.SECONDS)) {
|
if (!BUSINESS_THREAD_POOL.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||||
|
System.out.println("业务线程池强制关闭");
|
||||||
BUSINESS_THREAD_POOL.shutdownNow();
|
BUSINESS_THREAD_POOL.shutdownNow();
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
@ -103,4 +98,16 @@ public class ThreadPoolConfig {
|
||||||
|
|
||||||
System.out.println("线程池关闭完成");
|
System.out.println("线程池关闭完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取线程池状态信息
|
||||||
|
*/
|
||||||
|
public static String getThreadPoolStatus() {
|
||||||
|
ThreadPoolExecutor executor = (ThreadPoolExecutor) BUSINESS_THREAD_POOL;
|
||||||
|
return String.format("线程池状态 - 核心:%d, 活跃:%d, 完成:%d, 队列:%d",
|
||||||
|
executor.getCorePoolSize(),
|
||||||
|
executor.getActiveCount(),
|
||||||
|
executor.getCompletedTaskCount(),
|
||||||
|
executor.getQueue().size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue