簡體   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