[英]Netty ChannelGroup over ConcurrentHashMap
我正在開發一款基於netty的多人游戲服務器。 傳輸到客戶端的大多數消息都是特定於單個客戶端的,但有時我需要向所有客戶端廣播相同的消息。
我不確定是否有充分的理由在我自己的Map上使用ChannelGroup。 所以現在我有:
public class GameSession {
/* a map of all the players part of this game session */
private ConcurrentHashMap<String, PlayerHandler> players = new ConcurrentHashMap<String, PlayerHandler>();
private final ChannelGroup playersChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
PlayerHandler在哪里:
public class PlayerHandler extends SimpleChannelInboundHandler<IncomingMessage>
並包含有狀態成員變量。
當一個新玩家加入時(在完成一些邏輯之后),他將被添加到GameSession中:
public void addPlayer(PlayerHandler p) {
if (p.getGameSessionID().equals(this.gameId)) {
players.put(p.getPlayerID(), p); //add this player to our game session
playersChannels.add(p.getChannelFromCtx()); //get channel and add to ChannelGroup
}
}
假設玩家要求離開(或關閉連接),我想播放一條消息
public void notifyPlayerLeft(String exPlayer) {
//Broadcast message with the id of the player that left
for (Map.Entry<String, PlayerHandler> entry : players.entrySet()) {
PlayerHandler player = entry.getValue();
player.sendPlayerLeft(exPlayer);
}
}
其中sendPlayerLeft()是一個簡單的方法,它可以執行以下操作:
ctx.writeAndFlush(outgoingMsg)
如果我使用ChannelGroup,我可以這樣做:
playersChannels.writeAndFlush(outgoingMsg, matcher)
但我不確定為什么這是一個更好的主意。 Netty表示它是異步發生的但是由於PlayerHandler沒有自己的線程,不會像我在NotifyPlayerLeft()中那樣迭代對象也會異步嗎? 請注意,整個場景將由一個頻道/用戶/線程觸發。
我希望我的問題足夠清楚。 謝謝!
正如您在此處所看到的,Netty對組的默認寫入再次是一個簡單的迭代。 從這個意義上講,您的方法在性能和並發性方面應該沒有區別。 主要區別在於它將所有期貨收集到地圖中,這種分組可以幫助您跟蹤引發的任何問題。 但是,為什么要使用你的代碼已經實現了?
用信息更新它。 因此,雖然ChannelGroup
對於前面所述的簡單迭代很有用,但您也可以從API文檔中獲益。
Netty.io 4.1 ChannelGroup API文檔
關閉的頻道會自動從集合中刪除,因此您無需擔心添加的頻道的生命周期。 頻道可以屬於多個頻道組。
您可以通過擴展DefaultChannelGroup.class
來創建新的ChannelGroup.class
,並添加一些方法以在通道注銷期間添加其他行為,以通知某些代碼未注冊Channel,然后通知其他玩家,或者進行清理。
小心Netty的ConcurrentHashMap; 它實際上是馬車; 它不是線程安全的。 您可以在放置另一個線程時在一個線程上使用並發流來驗證此錯誤。 它並不總是失敗,因為它與非原子內部數組突變有關(快節奏並發r / w應該與netty但不是jdk失敗。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.