多執行緒狀態下HashMap和ConCurrentHashMap的執行比較
阿新 • • 發佈:2019-02-01
在專案實踐中,有的時候會使用單例模式來建立一些物件,這些物件在有兩個特點,1,整個記憶體中只有一個備份,2,操作的時候需要多執行緒操作。而這些物件有時需要一些快取資料。比如一個日誌收集系統,收到資料之後,可以使用一個全域性的單例的WebSocket池,根據不同的需求將資料傳送到不同的使用者。這個websocket池,就可以定義一個全域性的單例websocketsession物件,然後將使用者名稱和session以儲存到一個map中。這個map在被訪問時,很可能會被多執行緒訪問。所以在選擇資料結構上面最好選擇一個在多執行緒訪問的情況下可以被執行緒安全訪問的物件,最好使用ConCurrentHashMap.這篇文章將舉一個例子,驗證ConCurrentHashMap的執行緒安全性。
下面一個例子主要通過執行緒訪問角度,來驗證HashMap和ConCurrentHashMap的執行緒安全性。
package hashmap.test.testone; import java.util.HashMap; public class MainClass{ public static final HashMap<String,String> firstHashMap = new HashMap<String,String>(); public static void main(String[] args) throws InterruptedException{ //執行緒一 Thread t1 = new Thread(){ public void run(){ for(int i = 0;i<50;i++){ firstHashMap.put(String.valueOf(i), String.valueOf(i)); } } }; //執行緒二 Thread t2 = new Thread(){ public void run(){ for(int j = 50;j<100;j++){ firstHashMap.put(String.valueOf(j), String.valueOf(j)); } } }; t2.start(); t1.start(); //主執行緒休眠1秒鐘,以便t1和t2兩個執行緒將firstHashMap填裝完畢。 Thread.currentThread().sleep(1000); for(int l =0;l <100;l++){ //如果key和value不同,說明兩個執行緒在put的過程出現異常 if(!String.valueOf(l).equals(firstHashMap.get(String.valueOf(l)))){ System.out.println(String.valueOf(l)+": "+firstHashMap.get(String.valueOf(l))); } } } }
使用HashMap儲存資料,在多執行緒訪問情況下出現的異常如下圖:
本人做了15此實驗,出錯次數如下圖:
使用ConcurrentHashMap,程式碼如下:
import java.util.concurrent.ConcurrentHashMap; public class ConCurrentClass { public static final ConcurrentHashMap<String, String> firstHashMap = new ConcurrentHashMap<String,String>(); public static void main(String[] args) throws InterruptedException{ //執行緒一 Thread t1 = new Thread(){ public void run(){ for(int i = 0;i<50;i++){ firstHashMap.put(String.valueOf(i), String.valueOf(i)); } } }; //執行緒二 Thread t2 = new Thread(){ public void run(){ for(int j = 50;j<100;j++){ firstHashMap.put(String.valueOf(j), String.valueOf(j)); } } }; t2.start(); t1.start(); //主執行緒休眠1秒鐘,以便t1和t2兩個執行緒將firstHashMap填裝完畢。 Thread.currentThread().sleep(1000); for(int l =0;l <100;l++){ //如果key和value不同,說明兩個執行緒在put的過程出現異常 if(!String.valueOf(l).equals(firstHashMap.get(String.valueOf(l)))){ System.out.println(String.valueOf(l)+": "+firstHashMap.get(String.valueOf(l))); } } } }
當使用ConcurrentHashMap時在多執行緒訪問的情況下,沒有出現任何異常資訊。
所以本人建議,在多執行緒訪問的時候,使用ConCurrentHashMap物件,當然這也是官方推薦的方法。當然還有ConcurrentHashMap和HashMap的效率,有時間的話,本人將試圖做這方面的總結。