修改长沙麻将线程池

master
zhouwei 2026-02-26 19:28:54 +08:00
parent 74ce44217e
commit 032cd2d46c
8 changed files with 361 additions and 161 deletions

View File

@ -22,6 +22,9 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; 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); GroupRoomBusiness.joinRoom(groupId, roomId, robotSession, null);
Thread.sleep(5000); //非阻塞延迟替代Thread.sleep
scheduleDelay(() -> {
}, 5, TimeUnit.SECONDS);
params.del("groupId"); params.del("groupId");
params.del("roomId"); params.del("roomId");
@ -347,7 +353,10 @@ public class EXGameController extends GameController {
//先不放入映射 等确认加入成功后再放入 //先不放入映射 等确认加入成功后再放入
//robotRoomMapping.put(robotUser.getConnecId(), robotUser); //robotRoomMapping.put(robotUser.getConnecId(), robotUser);
robotRoomMapping.remove(robotUser.getRobotId()); robotRoomMapping.remove(robotUser.getRobotId());
Thread.sleep(2000); //非阻塞延迟替代Thread.sleep
scheduleDelay(() -> {
}, 2, TimeUnit.SECONDS);
params.putString("session", "{user}:" + robotId + "," + robotSession); params.putString("session", "{user}:" + robotId + "," + robotSession);
//发送加入房间请求到game_mj_cs //发送加入房间请求到game_mj_cs
@ -371,14 +380,21 @@ public class EXGameController extends GameController {
//添加超时检查机制 //添加超时检查机制
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
try { try {
Thread.sleep(15000); //定时任务替代Thread.sleep
//10秒后还没有建立映射关系 加入可能失败 scheduleDelay(() -> {
//15秒后还没有建立映射关系 加入可能失败
if (robotRoomMapping.get(robotUser.getConnecId()) == null) { if (robotRoomMapping.get(robotUser.getConnecId()) == null) {
System.err.println("机器人{"+robotId+"}加入房间{"+roomId+"}超时,清理临时状态"); System.err.println("机器人{"+robotId+"}加入房间{"+roomId+"}超时,清理临时状态");
robotConnectionManager.disconnectFromGameServer(connecId); robotConnectionManager.disconnectFromGameServer(connecId);
} }
} catch (InterruptedException e) { }, 15, TimeUnit.SECONDS);
Thread.currentThread().interrupt(); //15秒后还没有建立映射关系 加入可能失败
if (robotRoomMapping.get(robotUser.getConnecId()) == null) {
System.err.println("机器人{"+robotId+"}加入房间{"+roomId+"}超时,清理临时状态");
robotConnectionManager.disconnectFromGameServer(connecId);
}
} catch (Exception e) {
log.error("机器人加入房间超时", e);
} }
}); });
robotUser.setIntoRoomTime(robotConnectionManager.getTime()); robotUser.setIntoRoomTime(robotConnectionManager.getTime());

View File

@ -28,6 +28,27 @@ public class EXMainServer extends MainServer{
public void onStart() { public void onStart() {
super.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. 先启动独立的事件处理线程(只启动一次) // 1. 先启动独立的事件处理线程(只启动一次)
startNetEventThread(); startNetEventThread();

View File

@ -12,6 +12,7 @@ import com.taurus.core.util.Logger;
import com.taurus.core.util.StringUtil; import com.taurus.core.util.StringUtil;
import robot.mj.business.AccountBusiness; import robot.mj.business.AccountBusiness;
import robot.mj.info.RobotUser; import robot.mj.info.RobotUser;
import robot.mj.thread.ThreadPoolConfig;
import taurus.client.Message; import taurus.client.Message;
import taurus.client.MessageResponse; import taurus.client.MessageResponse;
import taurus.client.TaurusClient; import taurus.client.TaurusClient;
@ -22,6 +23,10 @@ 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.EXGameController.robotRoomMapping; import static robot.mj.EXGameController.robotRoomMapping;
@ -292,14 +297,31 @@ public class RobotConnectionManager {
} }
} }
sleepTime(2000); //非阻塞的延迟执行,增加更完善的异常处理
scheduleDelay(() -> {
try {
//重新获取当前实例,确保数据一致性
HuNanChangSha reconnectedInstance = getHuNanChangShaInstance(connecId);
Map<Integer, List<Integer>> currentPlayerOutcardsMap = getPlayerOutcardsMap(connecId); Map<Integer, List<Integer>> currentPlayerOutcardsMap = getPlayerOutcardsMap(connecId);
Map<Integer, List<Integer>> currentPlayerchisMap = getPlayerchisMap(connecId); Map<Integer, List<Integer>> currentPlayerchisMap = getPlayerchisMap(connecId);
Map<Integer, List<Integer>> currentPlayerpengsMap = getPlayerpengsMap(connecId); Map<Integer, List<Integer>> currentPlayerpengsMap = getPlayerpengsMap(connecId);
Map<Integer, List<Integer>> currentPlayermingsMap = getPlayermingsMap(connecId); Map<Integer, List<Integer>> currentPlayermingsMap = getPlayermingsMap(connecId);
Map<Integer, List<Integer>> currentPlayerzisMap = getPlayerzisMap(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 { } else {
System.err.println("警告:重连时未获取到手牌数据"); System.err.println("警告:重连时未获取到手牌数据");
} }
@ -307,7 +329,7 @@ public class RobotConnectionManager {
} }
} }
}catch (Exception e) { }catch (Exception e) {
e.printStackTrace(); log.error("机器人断线重连异常");
} }
}else { }else {
renconnect(robotUser); renconnect(robotUser);
@ -481,14 +503,15 @@ public class RobotConnectionManager {
} }
//2026.02.03修改 玩家加入房间 //2026.02.03修改 玩家加入房间
else if ("2001".equalsIgnoreCase(command)) { else if ("2001".equalsIgnoreCase(command)) {
CompletableFuture.runAsync(() -> { //直接使用定时任务替代Thread.sleep避免嵌套异步调用
sleepTime(6000); scheduleDelay(() -> {
Jedis jedis = Redis.use().getJedis();
try {
String roomKey = String.valueOf(robotUser.getCurrentRoomId()); String roomKey = String.valueOf(robotUser.getCurrentRoomId());
//查询该房间的玩家信息 //查询该房间的玩家信息
String playersStr = jedis0.hget("room:"+roomKey, "players"); String playersStr = jedis.hget("room:"+roomKey, "players");
if (!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(",");
@ -496,7 +519,6 @@ 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 == robotId) { if (playerId == robotId) {
//发送退出房间协议 //发送退出房间协议
ITObject params = TObject.newInstance(); ITObject params = TObject.newInstance();
client.send("1005", params, response -> { client.send("1005", params, response -> {
@ -504,24 +526,33 @@ public class RobotConnectionManager {
//更新机器人剩余数量 //更新机器人剩余数量
updateLeftoverRobot(robotId); updateLeftoverRobot(robotId);
disconnectFromGameServer(connecId); disconnectFromGameServer(connecId);
System.out.println("2002发送退出房间协议1005robotId: {"+robotId+"}"); System.out.println("2001发送退出房间协议1005robotId: {"+robotId+"}");
}); });
} }
} }
} }
}); } catch (Exception e) {
log.error("处理玩家加入房间检查时发生异常", e);
} finally {
// 确保Jedis连接关闭
if (jedis != null) {
jedis.close();
}
}
}, 6, TimeUnit.SECONDS);
System.out.println("玩家{"+ robotUser.getCurrentRoomId()+"}加入房间:"+ param); System.out.println("玩家{"+ robotUser.getCurrentRoomId()+"}加入房间:"+ param);
} }
//2026.02.03修改 玩家退出房间也要检查 //2026.02.03修改 玩家退出房间也要检查
else if ("2002".equalsIgnoreCase(command)) { else if ("2002".equalsIgnoreCase(command)) {
CompletableFuture.runAsync(() -> { //直接使用定时任务替代Thread.sleep避免嵌套异步调用
sleepTime(6000); scheduleDelay(() -> {
Jedis jedis = Redis.use().getJedis();
try {
String roomKey = String.valueOf(robotUser.getCurrentRoomId()); String roomKey = String.valueOf(robotUser.getCurrentRoomId());
//查询该房间的玩家信息 //查询该房间的玩家信息
String playersStr = jedis0.hget("room:"+roomKey, "players"); String playersStr = jedis.hget("room:"+roomKey, "players");
if (!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(",");
@ -529,7 +560,6 @@ 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 == robotId) { if (playerId == robotId) {
//发送退出房间协议 //发送退出房间协议
ITObject params = TObject.newInstance(); ITObject params = TObject.newInstance();
client.send("1005", params, response -> { client.send("1005", params, response -> {
@ -542,7 +572,14 @@ public class RobotConnectionManager {
} }
} }
} }
}); } catch (Exception e) {
log.error("处理玩家退出房间检查时发生异常", e);
} finally {
if (jedis != null) {
jedis.close();
}
}
}, 6, TimeUnit.SECONDS);
} }
//2026.02.05修改 玩家解散房间 //2026.02.05修改 玩家解散房间
else if ("2005".equalsIgnoreCase(command)) { else if ("2005".equalsIgnoreCase(command)) {
@ -559,16 +596,17 @@ public class RobotConnectionManager {
} }
//2026.02.03修改 通过机器人房间映射直接获取房间信息 //2026.02.03修改 通过机器人房间映射直接获取房间信息
else if ("2009".equalsIgnoreCase(command)) { else if ("2009".equalsIgnoreCase(command)) {
CompletableFuture.runAsync(() -> { //直接使用定时任务替代Thread.sleep避免嵌套异步调用
scheduleDelay(() -> {
Jedis localJedis = Redis.use().getJedis();
try {
Integer paramRobotId = param.getInt("aid"); Integer paramRobotId = param.getInt("aid");
sleepTime(6000);
if (robotUser != null) { if (robotUser != null) {
String roomKey = String.valueOf(robotUser.getCurrentRoomId()); String roomKey = String.valueOf(robotUser.getCurrentRoomId());
//查询该房间的玩家信息 //查询该房间的玩家信息
String playersStr = jedis0.hget(roomKey, "players"); String playersStr = localJedis.hget(roomKey, "players");
if (!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(",");
@ -576,8 +614,7 @@ 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 = jedis0.hget(roomKey, "gpid");
//更新机器人剩余数量 //更新机器人剩余数量
if (count != null && count.containsKey(Integer.parseInt(gpid))) { if (count != null && count.containsKey(Integer.parseInt(gpid))) {
@ -601,7 +638,14 @@ public class RobotConnectionManager {
} }
} }
} }
}); } catch (Exception e) {
log.error("处理机器人房间映射检查时发生异常", e);
} finally {
if (localJedis != null) {
localJedis.close();
}
}
}, 6, TimeUnit.SECONDS);
} }
//结算 //结算
else if ("817".equalsIgnoreCase(command)) { else if ("817".equalsIgnoreCase(command)) {
@ -624,9 +668,6 @@ public class RobotConnectionManager {
//更新机器人剩余数量 //更新机器人剩余数量
updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId())); updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
} }
sleepTime(1000);
ITObject params = TObject.newInstance(); ITObject params = TObject.newInstance();
params.putString("session", client.getSession()); params.putString("session", client.getSession());
client.send("1003", params, new ICallback<MessageResponse>() { client.send("1003", params, new ICallback<MessageResponse>() {
@ -675,7 +716,7 @@ public class RobotConnectionManager {
}); });
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); log.error("处理接收到的游戏协议");
} finally { } finally {
jedis0.close(); jedis0.close();
jedis2.close(); jedis2.close();
@ -739,7 +780,7 @@ public class RobotConnectionManager {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); log.error("机器人登录异常");
} }
} }
@ -753,8 +794,8 @@ public class RobotConnectionManager {
robotUser.setIsconnect(client.isConnected()); robotUser.setIsconnect(client.isConnected());
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException e) { } catch (Exception e) {
throw new RuntimeException(e); log.error("连接游戏服务器时发生异常", e);
} }
robotUser.setClient(client); robotUser.setClient(client);
EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser); EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser);
@ -771,8 +812,8 @@ public class RobotConnectionManager {
robotUser.setIsconnect(client.isConnected()); robotUser.setIsconnect(client.isConnected());
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException e) { } catch (Exception e) {
throw new RuntimeException(e); log.error("重新连接游戏服务器时发生异常", e);
} }
robotUser.setClient(client); robotUser.setClient(client);
EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser); EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser);
@ -811,7 +852,7 @@ public class RobotConnectionManager {
//添加延迟 //添加延迟
Thread.sleep(time); Thread.sleep(time);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); System.out.println(e);
} }
} }

View File

@ -21,12 +21,14 @@ import com.taurus.web.Controller;
import com.taurus.web.WebException; import com.taurus.web.WebException;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import java.sql.SQLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
public class AccountBusiness extends Controller { 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 static Logger logger = Logger.getLogger(AccountBusiness.class);
private ITObject fillLoginData(String session, int accountid) { private ITObject fillLoginData(String session, int accountid) {
@ -101,7 +103,7 @@ public class AccountBusiness extends Controller {
if (StringUtil.isNotEmpty(idPwdBan)) if (StringUtil.isNotEmpty(idPwdBan))
{ {
logger.error("id:"+acc_bean.id+" ban login"); logger.error("id:"+acc_bean.id+" ban login");
throw new WebException(ErrorCode.BAN_LOGIN); //throw new WebException(ErrorCode.BAN_LOGIN);
} }
resData.putString("token", token); resData.putString("token", token);
return resData; 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"); logger.info("id:" + id + " login");
Jedis jedis0 = Redis.use("group1_db0").getJedis(); Jedis jedis0 = Redis.use("group1_db0").getJedis();
@ -145,11 +147,16 @@ public class AccountBusiness extends Controller {
if (StringUtil.isNotEmpty(idPwdBan)) { if (StringUtil.isNotEmpty(idPwdBan)) {
System.out.println("进入了77777777777777777777"); System.out.println("进入了77777777777777777777");
logger.error("id:" + id + " ban login"); logger.error("id:" + id + " ban login");
throw new WebException(ErrorCode.BAN_LOGIN); //throw new WebException(ErrorCode.BAN_LOGIN);
} }
System.out.println("进入了9999999999999"); System.out.println("进入了9999999999999");
ITArray resultArray = DataBase.use().executeQueryByTArray(sql); ITArray resultArray = null;
try {
resultArray = DataBase.use().executeQueryByTArray(sql);
} catch (SQLException e) {
log.error(e);
}
if (resultArray.size() == 0) { if (resultArray.size() == 0) {
if (Redis.use("group1_db0").exists(id + "_pwd_token")) { if (Redis.use("group1_db0").exists(id + "_pwd_token")) {
Redis.use("group1_db0").incrBy(id + "_pwd_token", 1); Redis.use("group1_db0").incrBy(id + "_pwd_token", 1);
@ -167,13 +174,13 @@ public class AccountBusiness extends Controller {
logger.error("pwd error count:" + count + " not login"); logger.error("pwd error count:" + count + " not login");
System.out.println("进入了00000000000"); System.out.println("进入了00000000000");
throw new WebException(ErrorCode._NO_SESSION); //throw new WebException(ErrorCode._NO_SESSION);
} }
} }
System.out.println("进入了111111111111"); System.out.println("进入了111111111111");
throw new WebException(ErrorCode._FAILED); //throw new WebException(ErrorCode._FAILED);
} }
ITObject userData = resultArray.getTObject(0); ITObject userData = resultArray.getTObject(0);

View File

@ -13,11 +13,11 @@ import taurus.client.TaurusClient;
import taurus.util.*; import taurus.util.*;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import static robot.mj.thread.ThreadPoolConfig.getBusinessThreadPool;
public class HuNanChangSha { public class HuNanChangSha {
@ -312,6 +312,28 @@ public class HuNanChangSha {
changShachuguopai.addAll(outCard); 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.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", id); params.putInt("id", id);
client.send("612", params, response -> { //使用延迟方法
}); delayedActionCard(client, params, "胡牌");
return "胡牌"; return "胡牌";
} }
} }
@ -429,8 +451,7 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "不开杠");
});
return "不开杠"; return "不开杠";
} }
@ -438,15 +459,13 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", id); params.putInt("id", id);
client.send("612", params, response -> { delayedActionCard(client, params, "开杠");
});
return "开杠"; return "开杠";
} else { } else {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "不开杠");
});
return "不开杠"; return "不开杠";
} }
} }
@ -468,8 +487,7 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "不开杠");
});
return "不开杠"; return "不开杠";
} }
@ -477,15 +495,13 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", id); params.putInt("id", id);
client.send("612", params, response -> { delayedActionCard(client, params, "开杠");
});
return "开杠"; return "开杠";
} else { } else {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "不开杠");
});
return "不开杠"; return "不开杠";
} }
} }
@ -505,24 +521,22 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "不开杠");
});
return "不开杠"; return "不开杠";
} }
Util.removeCard(changShaCardInhand, card, 1); Util.removeCard(changShaCardInhand, card, 1);
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", id); params.putInt("id", id);
client.send("612", params, response -> { delayedActionCard(client, params, "开杠");
});
return "开杠"; return "开杠";
} else { } else {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "不开杠");
});
return "不开杠"; return "不开杠";
} }
} }
@ -560,8 +574,8 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", id); params.putInt("id", id);
client.send("612", params, response -> { //使用延迟动作方法
}); delayedActionCard(client, params, "胡牌");
return "胡牌"; return "胡牌";
} }
//对应的数据 //对应的数据
@ -599,14 +613,14 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "");
});
return null; return null;
} else { } else {
//获取 //获取
ITObject tmp = null;
for (Map.Entry<Integer, ITObject> entry : idObject.entrySet()) { for (Map.Entry<Integer, ITObject> entry : idObject.entrySet()) {
if (entry.getKey() == changeid) { if (entry.getKey() == changeid) {
ITObject tmp = entry.getValue(); tmp = entry.getValue();
System.out.println("tmp ++++++++++= " + tmp); System.out.println("tmp ++++++++++= " + tmp);
if (tmp.getInt("type") == 2) { if (tmp.getInt("type") == 2) {
//碰 //碰
@ -635,9 +649,11 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", changeid); params.putInt("id", changeid);
client.send("612", params, response -> { //使用延迟动作方法
}); String actionName = (tmp.getInt("type") == 2) ? "碰牌" : "吃牌";
delayedActionCard(client, params, actionName);
return null; return null;
} }
} }
@ -678,8 +694,7 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "");
});
return null; return null;
} }
//去一张下听? //去一张下听?
@ -691,8 +706,7 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "补牌");
});
return null; return null;
} }
} }
@ -706,8 +720,7 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "");
});
return null; return null;
} else { } else {
@ -718,9 +731,8 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "不开杠");
}); return "不开杠";
return null;
} }
System.out.println("补"); System.out.println("补");
@ -750,8 +762,7 @@ public class HuNanChangSha {
gangdepai.add(card); gangdepai.add(card);
gangdepai.add(card); gangdepai.add(card);
} }
client.send("612", params, response -> { delayedActionCard(client, params, "");
});
return null; return null;
} }
@ -781,8 +792,7 @@ public class HuNanChangSha {
gangdepai.add(card); gangdepai.add(card);
gangdepai.add(card); gangdepai.add(card);
} }
client.send("612", params, response -> { delayedActionCard(client, params, "补牌");
});
return null; return null;
} }
} }
@ -791,8 +801,7 @@ public class HuNanChangSha {
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
params.putInt("qi", 0); params.putInt("qi", 0);
params.putInt("id", 0); params.putInt("id", 0);
client.send("612", params, response -> { delayedActionCard(client, params, "默认动作");
});
return null; return null;
} }
@ -873,7 +882,8 @@ public class HuNanChangSha {
System.out.println("打过后的手牌 +++ " + changShaCardInhand); System.out.println("打过后的手牌 +++ " + changShaCardInhand);
params.putString("session", session + "," + token); params.putString("session", session + "," + token);
CompletableFuture.runAsync(() -> { //使用线程池替代CompletableFuture.runAsync + Thread.sleep
getBusinessThreadPool().execute(() -> {
try { try {
int ot = new Random().nextInt(4); int ot = new Random().nextInt(4);
Thread.sleep(ot*1000); Thread.sleep(ot*1000);
@ -882,7 +892,6 @@ public class HuNanChangSha {
}); });
} catch (Exception e) { } catch (Exception e) {
System.out.println("Thread error"); System.out.println("Thread error");
//Thread.currentThread().interrupt();
} }
}); });

View File

@ -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("线程池关闭完成");
}
}

View File

@ -23,7 +23,7 @@ public class ChangshaWinSplitCard {
// 检测不带精湖 // 检测不带精湖
public static int checkNormalHu(List<Integer> cardInHand, Map<String, Object> map) { public static int checkNormalHu(List<Integer> cardInHand, Map<String, Object> map) {
if (cardInHand == null || cardInHand.isEmpty()) { if (cardInHand == null || cardInHand.isEmpty()) {
throw new IllegalArgumentException("手牌不能为空"); //throw new IllegalArgumentException("手牌不能为空");
} }
String info = ""; String info = "";

View File

@ -31,7 +31,7 @@ public class ai {
public int findBestDiscard(PlayerState state) { public int findBestDiscard(PlayerState state) {
//参数验证 //参数验证
if (state == null || state.handCards == null) { if (state == null || state.handCards == null) {
throw new IllegalArgumentException("玩家状态和手牌不能为空"); //throw new IllegalArgumentException("玩家状态和手牌不能为空");
} }
System.out.println("\n=== 长沙麻将AI出牌分析 ==="); System.out.println("\n=== 长沙麻将AI出牌分析 ===");
System.out.println("手牌(" + state.handCards.size() + "张): " + this.formatCards(state.handCards)); System.out.println("手牌(" + state.handCards.size() + "张): " + this.formatCards(state.handCards));