繁体   English   中英

正确地从ConcurrentHashMap中删除值

[英]Removing Values from ConcurrentHashMap Properly

我正在制作一个简单的客户端服务器程序,该程序允许用户连接,更改其名称以及进入聊天室。 服务器会定期向每个客户端发送心跳信号(如果它们未处于活动状态),如果每个客户端均未响应,则将其删除。

为了进一步加强服务器清理,我还将定期检查我的房间是否空着,在这种情况下,我从服务器上删除了房间,以防止不必要的数据积累。 但是,此删除会带来问题。 我正在使用ConcurrentHashMap,它将房间名称映射到保存玩家名称及其插座的ConcurrentHashMap。 然后,定期地,我遍历每个房间,检查其中是否包含任何玩家(尺寸大于0)。 如果没有,我将房间移开。

但是,当服务器决定清理房间时,当用户选择加入空房间的确切时间时,这会带来非常麻烦的情况。 由于ConcurrentHashMap处理所有幕后同步,因此我无法同步此特定情况,因此删除是100%线程安全的。 用户可能正好在移开房间的同时加入房间,这导致他陷入了困境。

我该如何解决这个问题?

我将外部地图保留为ConcurrentHashMap,但将内部地图替换为ChatRoom类。 单个房间中的预期活动率似乎无法证明如此强大的并发图是合理的。

ChatRoom类应该是线程安全的,并且应具有“已关闭”标志,用于指示房间是否已关闭。 close()方法应使用房间的锁来更改标志,并使任何后续操作非法。 实际上,close方法应该返回一个布尔值,指示房间是否已经关闭; 当且仅当房间为空时,才应将其关闭。

您的空闲房间检查器线程应调用room.close(),然后将其从外部映射中删除。

您可以将同步方法添加到Room中,例如boolean closeIfEmpty() 如果成功,则可以安全地从地图上移除房间(使用2参数remove方法)。 如果添加代码尝试添加到封闭的房间,则添加操作将失败,并且调用方将创建一个新房间并替换该封闭的房间。

您可以在Room ConcurrentHashMap实例上同步删除操作和“向房间添加用户”操作,还可以在房间上保持“ closed”标志。

就像是

void scanRoomAndRemove(Map room) {
 synchronized (room) { 
   // scan room, remove from parent Map if empty
   room.put("closed",new Object());
 }
}

void addPlayerToRoom(Player player,Map room) {
 synchronized(room) {
  if ( !room.containsKey("closed")) {
    // add player to room  
  } else {
    // whine here
  }
 }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM