簡體   English   中英

ConcurrentHashMap put vs putIfAbsent

[英]ConcurrentHashMap put vs putIfAbsent

Java Docs說, putIfAbsent相當於

   if (!map.containsKey(key)) 
      return map.put(key, value);
   else
      return map.get(key);

因此,如果密鑰存在於地圖中,則不會更新其值。 它是否正確?

如果我想根據某些條件更新密鑰值怎么辦? 說過期時間等

這是否是添加和更新緩存的更好的方法?

public void AddToCache(T key, V value)
{
   V local = _cache.putifabsent(key, value);

   if(local.equals(value) && local.IsExpired() == false){
     return;
   }
   // this is for updating the cache with a new value
   _cache.put(key, value);
}

所以它不會更新密鑰的價值。 它是否正確?

那是正確的。 它將返回Map中已有的當前值。

這是添加和更新緩存的更好的方法嗎?

一些事情會使您的實施更好。

1.你不應該使用putIfAbsent來測試它是否存在,你應該只在你想要確保一個不存在時使用它然后putIfAbsent 相反,你應該使用map.get來測試它的存在(或map.contains)。

    V local = _cache.get(key);
    if (local.equals(value) && !local.IsExpired()) {
        return;
    }

2.而不是放置你想要替換,這是因為可能發生競爭條件,其中if可以被兩個或多個線程評估為false,其中兩個(或更多)線程中的一個將覆蓋其他線程的puts。

你能做的就是替換

完成所有操作后,它可能看起來像這樣

public void AddToCache(T key, V value) {
    for (;;) {

        V local = _cache.get(key);
        if(local == null){
            local = _cache.putIfAbsent(key, value);
            if(local == null)
                return;
        }
        if (local.equals(value) && !local.IsExpired()) {
            return;
        }

        if (_cache.replace(key, local, value))
            return;
    }
}

如果密鑰以前不在地圖中,您的代碼將拋出NPE。

除此之外,雖然這是一個合理的想法,但它不適用於“ 並發 ”環境。 添加putIfAbsent()方法的原因是,映射可以使用它用於使操作線程安全的任何底層支持來管理操作的原子性。 在您的實現中,2個不同的調用者可能會相互踩踏(第一個用新值替換過期值,第二個立即用第二個新值替換第一個新值)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM