欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ConcurrentMap.putIfAbsent(key,value)用法實例

 更新時間:2018年02月05日 11:20:20   作者:藍精靈lx  
這篇文章主要介紹了ConcurrentMap.putIfAbsent(key,value)用法實例,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下

本文研究的主要是ConcurrentMap.putIfAbsent(key,value)用法的相關內容,具體如下。

業(yè)務上經常會遇到有這種場景,全局維護一個并發(fā)的ConcurrentMap, Map的每個Key對應一個對象,這個對象需要只創(chuàng)建一次。如果Map中該key對應的value不存在則創(chuàng)建,否則直接返回。

我們先看一下代碼:

public static Locale getInstance(String language, String country,  
      String variant) {  
    //...  
    String key = some_string;  
    Locale locale = map.get(key);  
    if (locale == null) {  
      locale = new Locale(language, country, variant);  
      map.put(key, locale);  
    }  
    return locale;  
  }  

這段代碼要做的事情是:

  1. 調用 map.get(key) 方法,判斷 map 里面是否有該 key 對應的 value (Locale 對象)。
  2. 如果返回 null,表示 map 里面沒有要查找的 key-value mapping。new 一個 Locale 對象,并把 new 出來的這個對象與 key 一起放入 map。
  3. 最后返回新創(chuàng)建的 Locale 對象

我們期望每次調用 getInstance 方法時要保證相同的 key 返回同一個 Local 對象引用。這段代碼能實現(xiàn)這個需求嗎?

答案是:在單線程環(huán)境下可以滿足要求,但是在多線程環(huán)境下會存在線程安全性問題,即不能保證在并發(fā)的情況相同的 key 返回同一個 Local 對象引用。

這是因為在上面的代碼里存在一個習慣被稱為 put-if-absent 的操作 [1],而這個操作存在一個 race condition:

if (locale == null) {  
  locale = new Locale(language, country, variant);  
  map.put(key, locale);  
} 

因為在某個線程做完 locale == null 的判斷到真正向 map 里面 put 值這段時間,其他線程可能已經往 map 做了 put 操作,這樣再做 put 操作時,同一個 key 對應的 locale 對象被覆蓋掉,最終 getInstance 方法返回的同一個 key 的 locale 引用就會出現(xiàn)不一致的情形。所以對 Map 的 put-if-absent 操作是不安全的(thread safty)。

為了解決這個問題,java 5.0 引入了 ConcurrentMap 接口,在這個接口里面 put-if-absent 操作以原子性方法 putIfAbsent(K key, V value) 的形式存在。正如 javadoc 寫的那樣:

putIfAbsent方法主要是在向ConcurrentHashMap中添加鍵—值對的時候,它會先判斷該鍵值對是否已經存在。

  • 如果不存在(新的entry),那么會向map中添加該鍵值對,并返回null。
  • 如果已經存在,那么不會覆蓋已有的值,直接返回已經存在的值。

對上面方法進行改造:

public static Locale getInstance(String language, String country,  
      String variant) {  
    //...  
    String key = some_string;  
    Locale locale = map.get(key);  
    if (locale == null) {  
      locale = new Locale(language, country, variant);  
      map.putIfAbsent(key, locale);  
    }  
    return locale;  
  }  

這段代碼使用了 Map 的 concurrent 形式(ConcurrentMap、ConcurrentHashMap),并簡單的使用了語句map.putIfAbsent(key, locale) 。這同樣不能保證相同的 key 返回同一個 Locale 對象引用。

這里的錯誤出在忽視了 putIfAbsent 方法是有返回值的,并且返回值很重要。

所以,使用 putIfAbsent 方法時切記要對返回值進行判斷。

public static Locale getInstance(String language, String country,  
      String variant) { 
    //...  
    String key = some_string;  
    Locale locale = map.get(key);  
    if (locale == null) {  
      locale = new Locale(language, country, variant);  
      Locale tmp = map.putIfAbsent(key, locale); 
      if (tmp != null) { 
        locale = tmp; 
      } 
    }  
    return locale;  
}  

【實例1】

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Test {
	public static void main(String[] args) {
		//測試一下currentHashMap.putIfAbsent() 
		Map<long, String> clientMap = new ConcurrentHashMap<>();
		System.out.println("首先打印空的clientMap");
		System.out.println("clientMap: " + clientMap);
		System.out.println();
		//在空的clientMap中添加一個新的記錄 
		System.out.println("在空的clientMap中添加一個新的記錄");
		System.out.println("添加之前的clientMap: " + clientMap);
		long netId = 1234567L;
		String str1 = "michael";
		String result = clientMap.putIfAbsent(netId, str1);
		System.out.println("添加之后的clientMap: " + clientMap);
		System.out.println("查看返回值result: " + result);
		System.out.println();
		//重復添加 
		System.out.println("重復添加上一次的記錄");
		System.out.println("添加之前的clientMap: " + clientMap);
		String result2 = clientMap.putIfAbsent(netId, str1);
		System.out.println("添加之后的clientMap: " + clientMap);
		System.out.println("查看返回值result: " + result2);
		System.out.println();
	}
}

總結

以上就是本文關于ConcurrentMap.putIfAbsent(key,value)用法實例的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關文章

  • Activiti開發(fā)環(huán)境的配置

    Activiti開發(fā)環(huán)境的配置

    本篇文章主要內容介紹了Activiti開發(fā)環(huán)境的配置,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • Java?詳解Collection集合之ArrayList和HashSet

    Java?詳解Collection集合之ArrayList和HashSet

    本章具體介紹了ArrayList和HashSet兩種集合的基本使用方法和區(qū)別,圖解穿插代碼實現(xiàn)。?JAVA成仙路從基礎開始講,后續(xù)會講到JAVA高級,中間會穿插面試題和項目實戰(zhàn),希望能給大家?guī)韼椭?/div> 2022-03-03
  • Java 反射調用靜態(tài)方法的簡單實例

    Java 反射調用靜態(tài)方法的簡單實例

    下面小編就為大家?guī)硪黄狫ava 反射調用靜態(tài)方法的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • Java獲得指定區(qū)間數(shù)的方法

    Java獲得指定區(qū)間數(shù)的方法

    這篇文章主要介紹了Java獲得指定區(qū)間數(shù)的方法,涉及java數(shù)值運算的相關技巧,需要的朋友可以參考下
    2015-05-05
  • Spring注入值到Bean的三種方式

    Spring注入值到Bean的三種方式

    這篇文章主要為大家詳細介紹了Spring注入值到Bean的三種方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 解決javaBean規(guī)范導致json傳參首字母大寫將永遠獲取不到問題

    解決javaBean規(guī)范導致json傳參首字母大寫將永遠獲取不到問題

    這篇文章主要介紹了解決javaBean規(guī)范導致json傳參首字母大寫將永遠獲取不到問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java中printStackTrace()用法示例

    Java中printStackTrace()用法示例

    這篇文章主要給大家介紹了關于Java中printStackTrace()用法的相關資料,printStackTrace()方法一般與拋出異常搭配使用,效果是打印出異常位置,需要的朋友可以參考下
    2024-05-05
  • idea顯示springboot多服務啟動界面service操作

    idea顯示springboot多服務啟動界面service操作

    這篇文章主要介紹了idea顯示springboot多服務啟動界面service操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • spring的TransactionSynchronizationAdapter事務源碼解析

    spring的TransactionSynchronizationAdapter事務源碼解析

    這篇文章主要介紹了spring的TransactionSynchronizationAdapter事務源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • 關于@ComponentScan?TypeFilter自定義指定掃描bean的規(guī)則

    關于@ComponentScan?TypeFilter自定義指定掃描bean的規(guī)則

    這篇文章主要介紹了關于@ComponentScan?TypeFilter自定義指定掃描bean的規(guī)則,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09

最新評論