Browse Source

优化玩家对象池管理

johnclot69 4 months ago
parent
commit
cb525dd32b

+ 6 - 3
incubator-game/src/main/java/com/incubator/game/GGame.java

@@ -23,6 +23,7 @@ import com.incubator.game.data.entity.GlobalInfoPO;
 import com.incubator.game.data.jdbc.LSDBHandler;
 import com.incubator.game.listener.PublicListener;
 import com.incubator.game.player.GPlayer;
+import com.incubator.game.player.PlayerPool;
 import com.incubator.game.room.RoomManager;
 import com.incubator.game.timer.FlushDB;
 import com.incubator.game.timer.RefreshNewDay;
@@ -77,8 +78,8 @@ public class GGame extends AbstractService {
 
     /** 玩家心跳开关 **/
     public static boolean heartEnable = false;
-    /** 房间最大池容量 **/
-    public static int MAX_ROOM_POOL_SIZE = 100;
+    /** 最大空闲玩家数量 **/
+    public static int maxIdlePlayers = 100;
 
     /** 游戏世界的时间
      *  此两个时间最小精度为秒,不能用于超过精度一秒的时间计算
@@ -100,6 +101,9 @@ public class GGame extends AbstractService {
     /** http消息事件 **/
     public static Map<String, HttpRequestHandler> httpHandlers = new HashMap<>();
 
+    /** 玩家对象池 **/
+    public static PlayerPool playerPool = new PlayerPool();
+
     /** 本服所有在线玩家 */
     public static Map<String, GPlayer> onlinePlayers = new ConcurrentHashMap<>();
 
@@ -225,7 +229,6 @@ public class GGame extends AbstractService {
         }
     }
 
-
     /**
      * 3.初始化游戏数据
      */

+ 4 - 2
incubator-game/src/main/java/com/incubator/game/handler/LoginGameHandler.java

@@ -40,9 +40,11 @@ public class LoginGameHandler extends NetHandler {
 
 		// 创建player
 		String player_id = UUID.randomUUID().toString();
-		PlayerInfoPO playerInfoPO = PlayerUtil.createPlayer(player_id);
+		PlayerInfoPO playerInfoPO = new PlayerInfoPO();
+		playerInfoPO.player_id = player_id;
+		playerInfoPO.token = player_id;
 		playerInfoPO.name = "玩家" + username;
-		Player player = new Player(playerInfoPO);
+		Player player = PlayerUtil.createPlayer(playerInfoPO);
 
 		// 绑定session
 		player.bind(session, 0L, player.getId());

+ 2 - 0
incubator-game/src/main/java/com/incubator/game/listener/PublicListener.java

@@ -7,6 +7,7 @@ import com.incubator.game.GGame;
 import com.incubator.common.net.Connection;
 import com.incubator.game.player.GPlayer;
 import com.incubator.core.net.handler.listener.GameServerConnectionListener;
+import com.incubator.game.player.Player;
 import com.incubator.message.proto.CommonProto;
 import io.netty.buffer.ByteBuf;
 
@@ -39,6 +40,7 @@ public class PublicListener extends GameServerConnectionListener {
 			if (player != null && player.getSession() == connection) {
 				// 执行玩家登出操作
 				player.doLogout();
+				GGame.playerPool.releasePlayer((Player) player);
 			}
 		} catch (Exception e) {
 			logger.error("处理玩家退出时发生异常: ", e);

+ 13 - 0
incubator-game/src/main/java/com/incubator/game/player/Player.java

@@ -37,6 +37,19 @@ public class Player extends GPlayer {
         GGame.addPlayer(this);
     }
 
+    public void reset() {
+        this.data = new PlayerInfoPO();
+    }
+
+    /**
+     * 销毁玩家,释放资源
+     */
+    public void destroy() {
+        reset();
+        logger.debug("Player {} has been destroyed.", this.data.player_id);
+        this.doLogout();
+    }
+
     /**
      * 每日刷新
      */

+ 77 - 0
incubator-game/src/main/java/com/incubator/game/player/PlayerPool.java

@@ -0,0 +1,77 @@
+package com.incubator.game.player;
+
+import com.incubator.game.GGame;
+import com.incubator.game.data.entity.PlayerInfoPO;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 玩家对象池
+ */
+public final class PlayerPool {
+
+    private final Queue<Player> playerPool;
+    private final ScheduledExecutorService cleaner;
+
+    public PlayerPool() {
+        this.playerPool = new ConcurrentLinkedQueue<>();
+        this.cleaner = Executors.newSingleThreadScheduledExecutor();
+        // 定期清理空闲玩家
+        this.cleaner.scheduleAtFixedRate(this::cleanIdlePlayers, 10, 30, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 获取玩家对象
+     */
+    public Player acquirePlayer(PlayerInfoPO playerInfoPO) {
+        Player player = this.playerPool.poll();
+        if (player == null) {
+            player = new Player(playerInfoPO);
+        }
+        player.data = playerInfoPO;
+        return player;
+    }
+
+    /**
+     * 玩家下线,归还玩家对象
+     */
+    public void releasePlayer(Player player) {
+        if (player != null) {
+            // 重置玩家状态
+            player.reset();
+            // 放回池中
+            this.playerPool.offer(player);
+        }
+    }
+
+    /**
+     * 定期清理空闲玩家
+     */
+    private void cleanIdlePlayers() {
+        while (this.playerPool.size() > GGame.maxIdlePlayers) {
+            Player player = this.playerPool.poll();
+            if (player != null) {
+                // 销毁玩家,释放资源
+                player.destroy();
+            }
+        }
+    }
+
+    /**
+     * 关闭对象池
+     */
+    public void shutdown() {
+        this.cleaner.shutdownNow();
+        this.playerPool.forEach(Player::destroy);
+        this.playerPool.clear();
+    }
+
+    public int getAvailablePlayers() {
+        return this.playerPool.size();
+    }
+
+}

+ 13 - 13
incubator-game/src/main/java/com/incubator/game/util/PlayerUtil.java

@@ -4,12 +4,24 @@ import com.incubator.common.net.Connection;
 import com.incubator.game.GGame;
 import com.incubator.game.data.entity.PlayerInfoPO;
 import com.incubator.game.player.GPlayer;
+import com.incubator.game.player.Player;
 
 /**
  * 玩家工具类
  */
 public final class PlayerUtil {
 
+    /**
+     * 初始化创建玩家数据
+     *
+     * @return
+     */
+    public static Player createPlayer(PlayerInfoPO playerInfoPO) {
+        Player player = GGame.playerPool.acquirePlayer(playerInfoPO);
+        player.data = playerInfoPO;
+        return player;
+    }
+
     /** 根据账号查找玩家 */
     public static GPlayer getPlayerByUid(long uid) {
         if (uid <= 0) {
@@ -24,19 +36,7 @@ public final class PlayerUtil {
     }
 
     /**
-     * 初始化创建玩家数据
-     *
-     * @return
-     */
-    public static PlayerInfoPO createPlayer(String playerId) {
-        PlayerInfoPO po = new PlayerInfoPO();
-        po.player_id = playerId;
-        po.token = playerId;
-        return po;
-    }
-
-    /**
-     * ws获取在线玩家
+     * 获取在线玩家
      *
      * @param playerId
      * @return