修改长沙麻将线程池
parent
74ce44217e
commit
032cd2d46c
|
|
@ -22,6 +22,9 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static robot.mj.thread.ThreadPoolConfig.scheduleDelay;
|
||||
|
||||
/**
|
||||
* 长沙麻将游戏控制器 - 处理游戏协议
|
||||
|
|
@ -150,7 +153,10 @@ public class EXGameController extends GameController {
|
|||
|
||||
GroupRoomBusiness.joinRoom(groupId, roomId, robotSession, null);
|
||||
|
||||
Thread.sleep(5000);
|
||||
//非阻塞延迟替代Thread.sleep
|
||||
scheduleDelay(() -> {
|
||||
|
||||
}, 5, TimeUnit.SECONDS);
|
||||
|
||||
params.del("groupId");
|
||||
params.del("roomId");
|
||||
|
|
@ -347,7 +353,10 @@ public class EXGameController extends GameController {
|
|||
//先不放入映射 等确认加入成功后再放入
|
||||
//robotRoomMapping.put(robotUser.getConnecId(), robotUser);
|
||||
robotRoomMapping.remove(robotUser.getRobotId());
|
||||
Thread.sleep(2000);
|
||||
//非阻塞延迟替代Thread.sleep
|
||||
scheduleDelay(() -> {
|
||||
|
||||
}, 2, TimeUnit.SECONDS);
|
||||
params.putString("session", "{user}:" + robotId + "," + robotSession);
|
||||
|
||||
//发送加入房间请求到game_mj_cs
|
||||
|
|
@ -371,14 +380,21 @@ public class EXGameController extends GameController {
|
|||
//添加超时检查机制
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
Thread.sleep(15000);
|
||||
//10秒后还没有建立映射关系 加入可能失败
|
||||
//定时任务替代Thread.sleep
|
||||
scheduleDelay(() -> {
|
||||
//15秒后还没有建立映射关系 加入可能失败
|
||||
if (robotRoomMapping.get(robotUser.getConnecId()) == null) {
|
||||
System.err.println("机器人{"+robotId+"}加入房间{"+roomId+"}超时,清理临时状态");
|
||||
robotConnectionManager.disconnectFromGameServer(connecId);
|
||||
}
|
||||
}, 15, TimeUnit.SECONDS);
|
||||
//15秒后还没有建立映射关系 加入可能失败
|
||||
if (robotRoomMapping.get(robotUser.getConnecId()) == null) {
|
||||
System.err.println("机器人{"+robotId+"}加入房间{"+roomId+"}超时,清理临时状态");
|
||||
robotConnectionManager.disconnectFromGameServer(connecId);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (Exception e) {
|
||||
log.error("机器人加入房间超时", e);
|
||||
}
|
||||
});
|
||||
robotUser.setIntoRoomTime(robotConnectionManager.getTime());
|
||||
|
|
|
|||
|
|
@ -28,6 +28,27 @@ public class EXMainServer extends MainServer{
|
|||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
//JVM关闭钩子
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
log.info("收到JVM关闭信号,开始优雅关闭...");
|
||||
try {
|
||||
//关闭所有机器人连接
|
||||
for (Map.Entry<String, RobotUser> entry : robotRoomMapping.entrySet()) {
|
||||
RobotUser robotUser = entry.getValue();
|
||||
if (robotUser.getClient() != null && robotUser.getClient().isConnected()) {
|
||||
robotConnectionManager.disconnectFromGameServer(robotUser.getConnecId());
|
||||
}
|
||||
}
|
||||
|
||||
//关闭线程池
|
||||
robot.mj.thread.ThreadPoolConfig.shutdown();
|
||||
|
||||
log.info("优雅关闭完成");
|
||||
} catch (Exception e) {
|
||||
log.error("关闭过程中发生异常", e);
|
||||
}
|
||||
}));
|
||||
|
||||
// 1. 先启动独立的事件处理线程(只启动一次)
|
||||
startNetEventThread();
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.taurus.core.util.Logger;
|
|||
import com.taurus.core.util.StringUtil;
|
||||
import robot.mj.business.AccountBusiness;
|
||||
import robot.mj.info.RobotUser;
|
||||
import robot.mj.thread.ThreadPoolConfig;
|
||||
import taurus.client.Message;
|
||||
import taurus.client.MessageResponse;
|
||||
import taurus.client.TaurusClient;
|
||||
|
|
@ -22,6 +23,10 @@ import taurus.util.ROBOTEventType;
|
|||
|
||||
import java.util.*;
|
||||
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.EXGameController.robotRoomMapping;
|
||||
|
||||
|
|
@ -292,14 +297,31 @@ public class RobotConnectionManager {
|
|||
}
|
||||
}
|
||||
|
||||
sleepTime(2000);
|
||||
Map<Integer, List<Integer>> currentPlayerOutcardsMap = getPlayerOutcardsMap(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayerchisMap = getPlayerchisMap(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayerpengsMap = getPlayerpengsMap(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayermingsMap = getPlayermingsMap(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayerzisMap = getPlayerzisMap(connecId);
|
||||
//非阻塞的延迟执行,增加更完善的异常处理
|
||||
scheduleDelay(() -> {
|
||||
try {
|
||||
//重新获取当前实例,确保数据一致性
|
||||
HuNanChangSha reconnectedInstance = getHuNanChangShaInstance(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayerOutcardsMap = getPlayerOutcardsMap(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayerchisMap = getPlayerchisMap(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayerpengsMap = getPlayerpengsMap(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayermingsMap = getPlayermingsMap(connecId);
|
||||
Map<Integer, List<Integer>> currentPlayerzisMap = getPlayerzisMap(connecId);
|
||||
|
||||
currentInstance.outCard(client, currentPlayerOutcardsMap, currentPlayerchisMap, currentPlayerpengsMap, currentPlayermingsMap, currentPlayerzisMap);
|
||||
reconnectedInstance.outCard(client, currentPlayerOutcardsMap, currentPlayerchisMap, currentPlayerpengsMap, currentPlayermingsMap, currentPlayerzisMap);
|
||||
System.out.println("断线重连后成功执行出牌操作");
|
||||
} catch (Exception e) {
|
||||
log.error("断线重连后执行出牌操作时发生异常", e);
|
||||
//即使出牌失败,也要确保连接状态正确
|
||||
try {
|
||||
if (robotUser != null) {
|
||||
robotUser.setStatus(ROBOTEventType.ROBOT_INTOROOM_READY);
|
||||
}
|
||||
} catch (Exception statusEx) {
|
||||
log.error("更新机器人状态时发生异常", statusEx);
|
||||
}
|
||||
}
|
||||
}, 2, TimeUnit.SECONDS);
|
||||
} else {
|
||||
System.err.println("警告:重连时未获取到手牌数据");
|
||||
}
|
||||
|
|
@ -307,7 +329,7 @@ public class RobotConnectionManager {
|
|||
}
|
||||
}
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("机器人断线重连异常");
|
||||
}
|
||||
}else {
|
||||
renconnect(robotUser);
|
||||
|
|
@ -481,68 +503,83 @@ public class RobotConnectionManager {
|
|||
}
|
||||
//2026.02.03修改 玩家加入房间
|
||||
else if ("2001".equalsIgnoreCase(command)) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
sleepTime(6000);
|
||||
//直接使用定时任务替代Thread.sleep,避免嵌套异步调用
|
||||
scheduleDelay(() -> {
|
||||
Jedis jedis = Redis.use().getJedis();
|
||||
try {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis.hget("room:"+roomKey, "players");
|
||||
if (playersStr != null && !playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis0.hget("room:"+roomKey, "players");
|
||||
if (!playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == robotId) {
|
||||
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
System.out.println("2002发送退出房间协议1005,robotId: {"+robotId+"}");
|
||||
});
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == robotId) {
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
System.out.println("2001发送退出房间协议1005,robotId: {"+robotId+"}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理玩家加入房间检查时发生异常", e);
|
||||
} finally {
|
||||
// 确保Jedis连接关闭
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
System.out.println("玩家{"+ robotUser.getCurrentRoomId()+"}加入房间:"+ param);
|
||||
}
|
||||
//2026.02.03修改 玩家退出房间也要检查
|
||||
else if ("2002".equalsIgnoreCase(command)) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
sleepTime(6000);
|
||||
//直接使用定时任务替代Thread.sleep,避免嵌套异步调用
|
||||
scheduleDelay(() -> {
|
||||
Jedis jedis = Redis.use().getJedis();
|
||||
try {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis.hget("room:"+roomKey, "players");
|
||||
if (playersStr != null && !playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis0.hget("room:"+roomKey, "players");
|
||||
if (!playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == robotId) {
|
||||
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
System.out.println("2002发送退出房间协议1005,robotId: {"+robotId+"}");
|
||||
});
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == robotId) {
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(robotId));
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(robotId);
|
||||
disconnectFromGameServer(connecId);
|
||||
System.out.println("2002发送退出房间协议1005,robotId: {"+robotId+"}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理玩家退出房间检查时发生异常", e);
|
||||
} finally {
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
}
|
||||
//2026.02.05修改 玩家解散房间
|
||||
else if ("2005".equalsIgnoreCase(command)) {
|
||||
|
|
@ -559,49 +596,56 @@ public class RobotConnectionManager {
|
|||
}
|
||||
//2026.02.03修改 通过机器人房间映射直接获取房间信息
|
||||
else if ("2009".equalsIgnoreCase(command)) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
Integer paramRobotId = param.getInt("aid");
|
||||
sleepTime(6000);
|
||||
//直接使用定时任务替代Thread.sleep,避免嵌套异步调用
|
||||
scheduleDelay(() -> {
|
||||
Jedis localJedis = Redis.use().getJedis();
|
||||
try {
|
||||
Integer paramRobotId = param.getInt("aid");
|
||||
if (robotUser != null) {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
|
||||
if (robotUser != null) {
|
||||
String roomKey = String.valueOf(robotUser.getCurrentRoomId());
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = localJedis.hget(roomKey, "players");
|
||||
if (playersStr != null && !playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
|
||||
//查询该房间的玩家信息
|
||||
String playersStr = jedis0.hget(roomKey, "players");
|
||||
if (!playersStr.equals("[]")) {
|
||||
String players = playersStr.substring(1, playersStr.length() - 1);
|
||||
String[] playerIds = players.split(",");
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == paramRobotId) {
|
||||
String gpid = localJedis.hget(roomKey, "gpid");
|
||||
|
||||
//判断只有当前机器人一个玩家
|
||||
if (playerIds.length == 1) {
|
||||
int playerId = Integer.parseInt(playerIds[0].trim());
|
||||
if (playerId == paramRobotId) {
|
||||
|
||||
String gpid = jedis0.hget(roomKey, "gpid");
|
||||
|
||||
//更新机器人剩余数量
|
||||
if (count != null && count.containsKey(Integer.parseInt(gpid))) {
|
||||
Integer currentValue = count.get(Integer.parseInt(gpid));
|
||||
if (currentValue > 0) {
|
||||
count.put(Integer.parseInt(gpid), currentValue - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(paramRobotId));
|
||||
//断开连接
|
||||
disconnectFromGameServer(connecId);
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(paramRobotId);
|
||||
System.out.println("2009发送退出房间协议1005,robotId: {"+paramRobotId+"}");
|
||||
});
|
||||
if (count != null && count.containsKey(Integer.parseInt(gpid))) {
|
||||
Integer currentValue = count.get(Integer.parseInt(gpid));
|
||||
if (currentValue > 0) {
|
||||
count.put(Integer.parseInt(gpid), currentValue - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//发送退出房间协议
|
||||
ITObject params = TObject.newInstance();
|
||||
client.send("1005", params, response -> {
|
||||
EXGameController.removeRobotRoomInfo(String.valueOf(paramRobotId));
|
||||
//断开连接
|
||||
disconnectFromGameServer(connecId);
|
||||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(paramRobotId);
|
||||
System.out.println("2009发送退出房间协议1005,robotId: {"+paramRobotId+"}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理机器人房间映射检查时发生异常", e);
|
||||
} finally {
|
||||
if (localJedis != null) {
|
||||
localJedis.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 6, TimeUnit.SECONDS);
|
||||
}
|
||||
//结算
|
||||
else if ("817".equalsIgnoreCase(command)) {
|
||||
|
|
@ -624,9 +668,6 @@ public class RobotConnectionManager {
|
|||
//更新机器人剩余数量
|
||||
updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
|
||||
}
|
||||
|
||||
sleepTime(1000);
|
||||
|
||||
ITObject params = TObject.newInstance();
|
||||
params.putString("session", client.getSession());
|
||||
client.send("1003", params, new ICallback<MessageResponse>() {
|
||||
|
|
@ -675,7 +716,7 @@ public class RobotConnectionManager {
|
|||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
log.error("处理接收到的游戏协议");
|
||||
} finally {
|
||||
jedis0.close();
|
||||
jedis2.close();
|
||||
|
|
@ -739,7 +780,7 @@ public class RobotConnectionManager {
|
|||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
log.error("机器人登录异常");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -753,8 +794,8 @@ public class RobotConnectionManager {
|
|||
robotUser.setIsconnect(client.isConnected());
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (Exception e) {
|
||||
log.error("连接游戏服务器时发生异常", e);
|
||||
}
|
||||
robotUser.setClient(client);
|
||||
EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser);
|
||||
|
|
@ -771,8 +812,8 @@ public class RobotConnectionManager {
|
|||
robotUser.setIsconnect(client.isConnected());
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (Exception e) {
|
||||
log.error("重新连接游戏服务器时发生异常", e);
|
||||
}
|
||||
robotUser.setClient(client);
|
||||
EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser);
|
||||
|
|
@ -811,7 +852,7 @@ public class RobotConnectionManager {
|
|||
//添加延迟
|
||||
Thread.sleep(time);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@ import com.taurus.web.Controller;
|
|||
import com.taurus.web.WebException;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
public class AccountBusiness extends Controller {
|
||||
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(AccountBusiness.class);
|
||||
private static Logger logger = Logger.getLogger(AccountBusiness.class);
|
||||
|
||||
private ITObject fillLoginData(String session, int accountid) {
|
||||
|
|
@ -101,7 +103,7 @@ public class AccountBusiness extends Controller {
|
|||
if (StringUtil.isNotEmpty(idPwdBan))
|
||||
{
|
||||
logger.error("id:"+acc_bean.id+" ban login");
|
||||
throw new WebException(ErrorCode.BAN_LOGIN);
|
||||
//throw new WebException(ErrorCode.BAN_LOGIN);
|
||||
}
|
||||
resData.putString("token", token);
|
||||
return resData;
|
||||
|
|
@ -116,7 +118,7 @@ public class AccountBusiness extends Controller {
|
|||
}
|
||||
|
||||
|
||||
public final ITObject idPasswordLogin(int id, String password) throws Exception {
|
||||
public final ITObject idPasswordLogin(int id, String password) {
|
||||
logger.info("id:" + id + " login");
|
||||
|
||||
Jedis jedis0 = Redis.use("group1_db0").getJedis();
|
||||
|
|
@ -145,12 +147,17 @@ public class AccountBusiness extends Controller {
|
|||
if (StringUtil.isNotEmpty(idPwdBan)) {
|
||||
System.out.println("进入了77777777777777777777");
|
||||
logger.error("id:" + id + " ban login");
|
||||
throw new WebException(ErrorCode.BAN_LOGIN);
|
||||
//throw new WebException(ErrorCode.BAN_LOGIN);
|
||||
}
|
||||
System.out.println("进入了9999999999999");
|
||||
|
||||
ITArray resultArray = DataBase.use().executeQueryByTArray(sql);
|
||||
if (resultArray.size() == 0) {
|
||||
ITArray resultArray = null;
|
||||
try {
|
||||
resultArray = DataBase.use().executeQueryByTArray(sql);
|
||||
} catch (SQLException e) {
|
||||
log.error(e);
|
||||
}
|
||||
if (resultArray.size() == 0) {
|
||||
if (Redis.use("group1_db0").exists(id + "_pwd_token")) {
|
||||
Redis.use("group1_db0").incrBy(id + "_pwd_token", 1);
|
||||
} else {
|
||||
|
|
@ -167,13 +174,13 @@ public class AccountBusiness extends Controller {
|
|||
logger.error("pwd error count:" + count + " not login");
|
||||
System.out.println("进入了00000000000");
|
||||
|
||||
throw new WebException(ErrorCode._NO_SESSION);
|
||||
//throw new WebException(ErrorCode._NO_SESSION);
|
||||
|
||||
}
|
||||
}
|
||||
System.out.println("进入了111111111111");
|
||||
|
||||
throw new WebException(ErrorCode._FAILED);
|
||||
//throw new WebException(ErrorCode._FAILED);
|
||||
}
|
||||
|
||||
ITObject userData = resultArray.getTObject(0);
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ import taurus.client.TaurusClient;
|
|||
import taurus.util.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import static robot.mj.thread.ThreadPoolConfig.getBusinessThreadPool;
|
||||
|
||||
public class HuNanChangSha {
|
||||
|
||||
|
|
@ -312,6 +312,28 @@ public class HuNanChangSha {
|
|||
changShachuguopai.addAll(outCard);
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟执行吃碰胡动作,增加自然的停顿效果
|
||||
* @param client 客户端连接
|
||||
* @param params 动作参数
|
||||
*/
|
||||
private void delayedActionCard(TaurusClient client, ITObject params, String actionName) {
|
||||
//使用线程池执行延迟动作
|
||||
getBusinessThreadPool().execute(() -> {
|
||||
try {
|
||||
int delaySeconds = 1 + new Random().nextInt(2);
|
||||
System.out.println("执行" + actionName + "动作,延迟" + delaySeconds + "秒");
|
||||
Thread.sleep(delaySeconds * 1000);
|
||||
|
||||
client.send("612", params, response -> {
|
||||
System.out.println(actionName + "动作发送完成");
|
||||
});
|
||||
} catch (Exception e) {
|
||||
System.err.println("执行" + actionName + "动作时发生异常: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 吃,碰,杠,补,胡
|
||||
*
|
||||
|
|
@ -393,8 +415,8 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", id);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
//使用延迟方法
|
||||
delayedActionCard(client, params, "胡牌");
|
||||
return "胡牌";
|
||||
}
|
||||
}
|
||||
|
|
@ -429,8 +451,7 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "不开杠");
|
||||
return "不开杠";
|
||||
}
|
||||
|
||||
|
|
@ -438,15 +459,13 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", id);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "开杠");
|
||||
return "开杠";
|
||||
} else {
|
||||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "不开杠");
|
||||
return "不开杠";
|
||||
}
|
||||
}
|
||||
|
|
@ -468,8 +487,7 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "不开杠");
|
||||
return "不开杠";
|
||||
}
|
||||
|
||||
|
|
@ -477,15 +495,13 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", id);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "开杠");
|
||||
return "开杠";
|
||||
} else {
|
||||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "不开杠");
|
||||
return "不开杠";
|
||||
}
|
||||
}
|
||||
|
|
@ -505,24 +521,22 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "不开杠");
|
||||
return "不开杠";
|
||||
|
||||
}
|
||||
|
||||
Util.removeCard(changShaCardInhand, card, 1);
|
||||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", id);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "开杠");
|
||||
return "开杠";
|
||||
} else {
|
||||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "不开杠");
|
||||
return "不开杠";
|
||||
}
|
||||
}
|
||||
|
|
@ -560,8 +574,8 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", id);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
//使用延迟动作方法
|
||||
delayedActionCard(client, params, "胡牌");
|
||||
return "胡牌";
|
||||
}
|
||||
//对应的数据
|
||||
|
|
@ -599,14 +613,14 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "");
|
||||
return null;
|
||||
} else {
|
||||
//获取
|
||||
ITObject tmp = null;
|
||||
for (Map.Entry<Integer, ITObject> entry : idObject.entrySet()) {
|
||||
if (entry.getKey() == changeid) {
|
||||
ITObject tmp = entry.getValue();
|
||||
tmp = entry.getValue();
|
||||
System.out.println("tmp ++++++++++= " + tmp);
|
||||
if (tmp.getInt("type") == 2) {
|
||||
//碰
|
||||
|
|
@ -635,9 +649,11 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", changeid);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
//使用延迟动作方法
|
||||
String actionName = (tmp.getInt("type") == 2) ? "碰牌" : "吃牌";
|
||||
delayedActionCard(client, params, actionName);
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -678,8 +694,7 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "");
|
||||
return null;
|
||||
}
|
||||
//去一张下听?
|
||||
|
|
@ -691,8 +706,7 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "补牌");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -706,8 +720,7 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "");
|
||||
return null;
|
||||
} else {
|
||||
|
||||
|
|
@ -718,9 +731,8 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
return null;
|
||||
delayedActionCard(client, params, "不开杠");
|
||||
return "不开杠";
|
||||
}
|
||||
|
||||
System.out.println("补");
|
||||
|
|
@ -750,8 +762,7 @@ public class HuNanChangSha {
|
|||
gangdepai.add(card);
|
||||
gangdepai.add(card);
|
||||
}
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -781,8 +792,7 @@ public class HuNanChangSha {
|
|||
gangdepai.add(card);
|
||||
gangdepai.add(card);
|
||||
}
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "补牌");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -791,8 +801,7 @@ public class HuNanChangSha {
|
|||
params.putString("session", session + "," + token);
|
||||
params.putInt("qi", 0);
|
||||
params.putInt("id", 0);
|
||||
client.send("612", params, response -> {
|
||||
});
|
||||
delayedActionCard(client, params, "默认动作");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
@ -873,7 +882,8 @@ public class HuNanChangSha {
|
|||
System.out.println("打过后的手牌 +++ " + changShaCardInhand);
|
||||
params.putString("session", session + "," + token);
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
//使用线程池替代CompletableFuture.runAsync + Thread.sleep
|
||||
getBusinessThreadPool().execute(() -> {
|
||||
try {
|
||||
int ot = new Random().nextInt(4);
|
||||
Thread.sleep(ot*1000);
|
||||
|
|
@ -882,7 +892,6 @@ public class HuNanChangSha {
|
|||
});
|
||||
} catch (Exception e) {
|
||||
System.out.println("Thread error");
|
||||
//Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
package robot.mj.thread;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 线程池配置类
|
||||
*/
|
||||
public class ThreadPoolConfig {
|
||||
|
||||
// 优化后的线程池配置:针对机器人场景优化
|
||||
private static final ExecutorService BUSINESS_THREAD_POOL =
|
||||
new ThreadPoolExecutor(
|
||||
10, // 核心线程数 - 减少核心线程数
|
||||
50, // 最大线程数 - 降低最大线程数
|
||||
30, // 空闲线程存活时间 - 缩短存活时间
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(10000), // 增大队列容量,减少拒绝任务
|
||||
new ThreadFactory() {
|
||||
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r, "RobotBusinessThread-" + threadNumber.getAndIncrement());
|
||||
t.setDaemon(true);
|
||||
t.setPriority(Thread.NORM_PRIORITY - 2); // 进一步降低线程优先级
|
||||
return t;
|
||||
}
|
||||
},
|
||||
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:由调用线程执行
|
||||
);
|
||||
|
||||
// 添加定时任务线程池,专门处理延迟操作
|
||||
private static final ScheduledExecutorService SCHEDULED_EXECUTOR_SERVICE =
|
||||
Executors.newScheduledThreadPool(4, new ThreadFactory() {
|
||||
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r, "RobotScheduledThread-" + threadNumber.getAndIncrement());
|
||||
t.setDaemon(true);
|
||||
t.setPriority(Thread.NORM_PRIORITY - 2);
|
||||
return t;
|
||||
}
|
||||
});
|
||||
|
||||
public static ExecutorService getBusinessThreadPool() {
|
||||
return BUSINESS_THREAD_POOL;
|
||||
}
|
||||
|
||||
public static ScheduledExecutorService getScheduledExecutorService() {
|
||||
return SCHEDULED_EXECUTOR_SERVICE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行延迟任务,替代Thread.sleep
|
||||
*/
|
||||
public static void scheduleDelay(Runnable task, long delay, TimeUnit unit) {
|
||||
System.out.println("提交延迟任务: 延迟" + delay + " " + unit + ", 当前时间: " + System.currentTimeMillis());
|
||||
SCHEDULED_EXECUTOR_SERVICE.schedule(() -> {
|
||||
try {
|
||||
System.out.println("执行延迟任务开始: 当前时间: " + System.currentTimeMillis());
|
||||
task.run();
|
||||
System.out.println("执行延迟任务完成: 当前时间: " + System.currentTimeMillis());
|
||||
} catch (Exception e) {
|
||||
System.err.println("延迟任务执行异常: " + e.getMessage());
|
||||
}
|
||||
}, delay, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行周期性任务
|
||||
*/
|
||||
public static void scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
|
||||
SCHEDULED_EXECUTOR_SERVICE.scheduleAtFixedRate(task, initialDelay, period, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 优雅关闭线程池,释放资源
|
||||
*/
|
||||
public static void shutdown() {
|
||||
System.out.println("开始关闭线程池...");
|
||||
|
||||
// 关闭定时任务线程池
|
||||
SCHEDULED_EXECUTOR_SERVICE.shutdown();
|
||||
try {
|
||||
if (!SCHEDULED_EXECUTOR_SERVICE.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
SCHEDULED_EXECUTOR_SERVICE.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
SCHEDULED_EXECUTOR_SERVICE.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
// 关闭业务线程池
|
||||
BUSINESS_THREAD_POOL.shutdown();
|
||||
try {
|
||||
if (!BUSINESS_THREAD_POOL.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
BUSINESS_THREAD_POOL.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
BUSINESS_THREAD_POOL.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
System.out.println("线程池关闭完成");
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ public class ChangshaWinSplitCard {
|
|||
// 检测不带精湖
|
||||
public static int checkNormalHu(List<Integer> cardInHand, Map<String, Object> map) {
|
||||
if (cardInHand == null || cardInHand.isEmpty()) {
|
||||
throw new IllegalArgumentException("手牌不能为空");
|
||||
//throw new IllegalArgumentException("手牌不能为空");
|
||||
}
|
||||
|
||||
String info = "";
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public class ai {
|
|||
public int findBestDiscard(PlayerState state) {
|
||||
//参数验证
|
||||
if (state == null || state.handCards == null) {
|
||||
throw new IllegalArgumentException("玩家状态和手牌不能为空");
|
||||
//throw new IllegalArgumentException("玩家状态和手牌不能为空");
|
||||
}
|
||||
System.out.println("\n=== 长沙麻将AI出牌分析 ===");
|
||||
System.out.println("手牌(" + state.handCards.size() + "张): " + this.formatCards(state.handCards));
|
||||
|
|
|
|||
Loading…
Reference in New Issue