[英]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.