2015-08-08 61 views
0

我試圖用ConcurrentHashMap創建一個具有以下行爲的方法。使用ConcurrentHashMap進行多線程

  1. 閱讀
  2. 寫鎖
  3. 事先書面無鎖,
    1. 閱讀,看是否存在記錄,
    2. 如果仍然不存在,保存到數據庫,並添加記錄映射。
    3. 如果記錄存在以前的寫入,只需返回記錄。

我的想法。

private Object lock1 = new Object(); 

private ConcurrentHashMap<String, Object> productMap; 

private Object getProductMap(String name) { 

    if (productMap.isEmpty()) { 
     productMap = new ConcurrentHashMap<>(); 
    } 

    if (productMap.containsKey(name)) { 
     return productMap.get(name); 
    } 

    synchronized (lock1) { 
     if (productMap.containsKey(name)) { 
      return productMap.get(name); 
     } else { 
      Product product = new Product(name); 
      session.save(product); 
      productMap.putIfAbsent(name, product); 
     } 
    } 

} 

有人能幫我理解這是否是一種正確的方法嗎?

回答

1

這裏有幾個錯誤。

  • 如果productMap不能保證被初始化,您將在第一條語句得到一個NPE這種方法。
  • 如果地圖爲空,則不保證該方法返回任何內容。
  • 該方法不會在所有路徑上返回。
  • 該方法既不好名稱,也不必要;你正試圖模仿putIfAbsent這一半完成你的目標。
  • 你也不需要做任何同步; ConcurrentHashMap爲您的目的是線程安全的。

如果我要重寫這個,我會做一些不同的事情:

  • 急切實例化ConcurrentHashMap
  • 將其綁定到ConcurrentMap,而不是具體的類(所以ConcurrentMap<String, Product> productMap = new ConcurrentHashMap<>();
  • 將方法重命名爲putIfMissing並委託給putIfAbsent,如果結果爲null,某些邏輯將返回我想添加的相同記錄。上述絕對依賴於具有良好定義的equalshashCode方法,使得如果提供的相同namenew Product(name)會產生具有相同值的對象爲equalshashCodeProduct

  • 使用Optional避免任何NPE結果爲putIfAbsent,並提供更容易摘要的代碼。

上面的一個片段:

public Product putIfMissing(String key) { 
    Product product = new Product(key); 
    Optional<Product> result = 
     Optional.ofNullable(productMap.putIfAbsent(key, product)); 
    session.save(result.orElse(product)); 
    return result.orElse(product); 
} 
+0

一是想我說謝謝,但我有幾個問題,以確保我完全理解其中的邏輯。 1.如果在每次調用putIfMissing時實例化Product,是否會創建不必要的垃圾收集?我會在很短的時間內調用這個方法數百萬次,會造成任何不必要的垃圾收集? 2.如果它實際上是一個新產品,產品價值是否會與持久對象一起更新,以便它可用於調用putIfMissing的所有對象? 3.當產品已經存在時,究竟傳遞給session.save的是什麼?謝謝 –