2012-01-04 38 views
2

存在的關鍵在Java的ConcurrentMap,有remove(key, expectedValue),這將返回之一:獲得無論從ConcurrentMap.remove()

  • 預期值在那裏,已被刪除。
  • 期望值不存在,所以沒有被刪除。

但我希望得到的是一個:

  1. 預期值在那裏,已被刪除。
  2. 該鍵下有一個值,但不是預期的值,所以它沒有被刪除。
  3. 該密鑰下沒有任何值,所以它沒有被刪除。

如何以併發和線程安全的方式獲取此信息?


這是代碼我想safify

// attempt to remove the old session... 
if (!sessions.remove(player.getId(), existing)) { 
    // it was not removed... 
    if (sessions.containsKey(player.getId())) { // TODO threadsafe 
     // ...because in the meantime some other thread logged in as that user 
     throw new ServiceError(LobbyService.ERR_LOGIN_INVALID, Maps.create("reason", "already-logged-in")); 
    } else { 
     // ...because it was no longer there, which is as it should be 
    } 
} else { 
    // it was removed, which is bad, because it shouldn't have been there still 
    log.warn("Kicking old session of " + player.getId() + " failed"); 
} 

或全身:

if (!sessions.remove(key, expected)) { 
    if (sessions.containsKey(key)) { // TODO threadsafe 
     // 2 
    } else { 
     // 3 
    } 
} else { 
    // 1 
} 
+0

不應該是'sessions.remove(player.getId(),existing)'而不是'會話。刪除(會話,現有)'? – dogbane 2012-01-04 10:41:10

+0

你能描述一下你如何使用這張地圖的整體情況嗎? – axtavt 2012-01-04 11:02:07

+0

@dogbane Woops :) – 2012-01-04 16:28:07

回答

1

我沒有你們之間在doc看到什麼,你想要什麼瞭解。所以請讓我把事情寫下來。

  • A與值B相關聯。 remove(A, B)將返回true 刪除映射A-> B(這是你想要的)。
  • A與價值C相關聯。 remove(A, B)將返回false,映射A-> C不會被刪除(這是你想要的)。
  • A與無價值關聯。 remove(A, null)將返回false(這是你想要的)。

換句話說,它看起來像刪除正好做你想要的...或者也許你的代碼中有另一個錯誤。

+0

你完全描述我的問題,後兩種情況都沒有從地圖中刪除條目(這是我想要的),他們也返回相同的結果,'假',這是不夠的信息,因爲我需要區分代碼中的兩種情況。 – 2012-01-04 16:30:29

0

您可以使用AtomicReference來提供幫助。假設您使用非null的AtomicReference進行預處理,則可以嘗試使用謂詞引用的當前值爲existing來使會話中的值爲空。如果是,你從地圖否則的AtomicReference的當前值是什麼,目前已有

AtomicReference<Session> ref = session.get(player.getId()); 
if (ref.compareAndSet(existing,null) { 
    //1 
}else{ 
    Session current = ref.get(); 
    if(current != null){ 
     //2 
    }else{ 
     //3 
    } 
} 
0

此代碼似乎「已刪除」近提供你所要求的,但我不知道這是否給你你想要的。

請您詳細介紹一下您真正想做的事情嗎?

class Player {}; 
ConcurrentMap<String,Player> players = new ConcurrentHashMap(); 

void playerIDChanged(String id, Player oldPlayer, Player newPlayer) { 
    Player old = players.replace(id, newPlayer); 
    if (old == oldPlayer) { 
    // The expected value was there and has been REPLACED. 
    } else { 
    if (old == null) { 
     // There is no value under that key, so it has not been removed. 
    } else { 
     // There is a value under that key, but not the expected one, so it HAS been replaced. 
     // NB: This is slightly different from what you are asking for. 
    } 
    } 
}