Java 正确删除ConcurrentHashMap中的值
我正在制作一个简单的客户机-服务器程序,允许用户连接、更改他们的姓名并进入聊天室。如果每个客户机未处于活动状态,服务器会定期向其发送心跳信号,如果客户机没有响应,则会将其删除 为了进一步加强我的服务器清理,我还定期检查我的房间是否为空,在这种情况下,我会将房间从服务器上移除,以防止不必要的数据积累。但是,这种删除会产生一个问题。我使用的是ConcurrentHashMap,它将一个房间名映射到一个ConcurrentHashMap,其中包含玩家姓名及其套接字。然后,我周期性地遍历每个房间,检查是否包含任何玩家(大小>0)。如果没有,我就把房间搬走 然而,当服务器决定清理空房间时,当用户选择加入空房间的确切时间时,这就出现了一个非常有问题的情况。由于ConcurrentHashMap处理所有的底层同步,因此我无法同步此特定情况,以确保删除是100%线程安全的。用户可能会在房间被移除时加入房间,这会导致他陷入一种不确定的状态Java 正确删除ConcurrentHashMap中的值,java,client,concurrenthashmap,Java,Client,Concurrenthashmap,我正在制作一个简单的客户机-服务器程序,允许用户连接、更改他们的姓名并进入聊天室。如果每个客户机未处于活动状态,服务器会定期向其发送心跳信号,如果客户机没有响应,则会将其删除 为了进一步加强我的服务器清理,我还定期检查我的房间是否为空,在这种情况下,我会将房间从服务器上移除,以防止不必要的数据积累。但是,这种删除会产生一个问题。我使用的是ConcurrentHashMap,它将一个房间名映射到一个ConcurrentHashMap,其中包含玩家姓名及其套接字。然后,我周期性地遍历每个房间,检查是
如何解决此问题?您可以向文件室添加一个同步方法,例如
boolean closeIfEmpty()
。如果成功,您可以安全地从地图中删除房间(使用2参数remove方法)。如果添加代码试图添加到一个封闭的聊天室,那么添加应该失败,调用方将创建一个新的聊天室并替换该封闭的聊天室。我会将外部映射保留为ConcurrentHashMap,但将内部映射替换为聊天室类。单个房间的预期活动率似乎不能证明这样一个强大的并发映射是合理的
聊天室类应该是线程安全的,并且应该有一个“closed”标志,指示聊天室是否已关闭。close()方法应该使用文件室的锁来更改标志,并使任何后续操作非法。实际上,close方法应该返回一个布尔值,指示房间是否已关闭;当且仅当房间是空的时,它才应该关闭
空闲文件室检查器线程应调用room.close(),然后将其从外部映射中删除。您可以同步文件室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
}
}
}
如果先从地图上删除房间,然后检查是否有用户,该怎么办?如果有,请将房间重新添加到地图中。如果碰巧地图上有一个同名的新房间,你可以合并这两个房间。谢谢,这是个好主意。真不敢相信我居然没想到。使用Apache或其他一些网络API将使我不必再编写这些东西。但我想自己做是一个更好的学习过程。