Java ConcurrentHashMap上的Netty ChannelGroup

Java ConcurrentHashMap上的Netty ChannelGroup,java,concurrency,netty,Java,Concurrency,Netty,我正在开发一个基于netty的多人游戏服务器。 传输到客户端的大多数消息都是特定于单个客户端的 但有时我需要向所有客户广播相同的消息 我不确定是否有充分的理由在我自己的地图上使用ChannelGroup。 所以现在我有: public class GameSession { /* a map of all the players part of this game session */ private ConcurrentHashMap<String, PlayerHandler&

我正在开发一个基于netty的多人游戏服务器。 传输到客户端的大多数消息都是特定于单个客户端的 但有时我需要向所有客户广播相同的消息

我不确定是否有充分的理由在我自己的地图上使用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);
假设我想广播一条消息,因为一个播放机请求离开或关闭连接

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);

    }
}
如果我使用ChannelGroup,我可以这样做:

playersChannels.writeAndFlush(outgoingMsg, matcher)
但我不知道为什么这是个更好的主意。Netty声明它是异步发生的 但是由于PlayerHandler没有自己的线程,所以不会迭代对象 就像我在NotifyPlayerLeft中做的那样,它也将是异步的?请注意,整个场景将由一个通道/用户/线程触发

我希望我的问题足够清楚。
谢谢

如您所见,Netty对组的默认写入也是一个简单的迭代。从这个意义上讲,您的方法在性能和并发性方面应该没有区别。主要区别在于,它将所有未来收集到一张地图中,这种分组可以帮助您跟踪出现的任何问题。但是如果已经实现了,为什么还要使用代码呢?

用信息更新代码。因此,尽管ChannelGroup对于前面所述的简单迭代非常有用,但您也可以从API文档中获得这一好处

关闭的频道将自动从集合中删除,因此您无需担心添加频道的生命周期。一个通道可以属于多个通道组


您可以通过扩展DefaultChannelGroup.class来创建一个新的ChannelGroup.class,并添加一些方法来在频道取消注册期间添加其他行为,以通知某些代码某个频道已取消注册,然后通知其他玩家,或者进行清理

小心使用Netty的ConcurrentHashMap;它实际上是马车;它不是线程安全的。您可以在一个线程上使用并发流验证此错误,同时在另一个线程上使用。它并不总是失败,因为它与非原子内部阵列突变有关。快速并行r/w应该与netty而不是jdk失败。

这主要是一种设计选择。这使我只能在PlayerHandler中生成新消息,而不能在GameSession中生成新消息。谢谢你的回答!
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);

    }
}
ctx.writeAndFlush(outgoingMsg)
playersChannels.writeAndFlush(outgoingMsg, matcher)