- HashMap幾乎可以等價于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受為null的鍵值(key)和值(value),而Hashtable則不行)。
- HashMap是非synchronized,而Hashtable是synchronized,這意味着Hashtable是線程安全的,多個線程可以共享一個Hashtable;而如果沒有正确的同步的話,多個線程是不能共享HashMap的。同步的HashMap可以用以下語句構造:Map m = Collections.synchronizeMap(hashMap);
- Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴充性更好。
- 另一個差別是HashMap的疊代器(Iterator)是fail-fast(注1)疊代器,而Hashtable的enumerator疊代器不是fail-fast的。是以當有其它線程改變了HashMap的結構(增加或者移除元素),将會抛出ConcurrentModificationException,但疊代器本身的remove()方法移除元素則不會抛出ConcurrentModificationException異常。但這并不是一個一定發生的行為,要看JVM。這條同樣也是Enumeration和Iterator的差別。
- 由于Hashtable是線程安全的也是synchronized,是以在單線程環境下它比HashMap要慢。如果你不需要同步,隻需要單一線程,那麼使用HashMap性能要好過Hashtable。
- HashMap不能保證随着時間的推移Map中的元素次序是不變的。
注1:Fail-safe和iterator疊代器相關。如果某個集合對象建立了Iterator或者ListIterator,然後其它的線程試圖“結構上”更改集合對象,将會抛出ConcurrentModificationException異常。但其它線程可以通過set()方法更改集合對象是允許的,因為這并沒有從“結構上”更改集合。但是假如已經從結構上進行了更改,再調用set()方法,将會抛出IllegalArgumentException異常。
HashTable和ConcurrentHashMap更詳細的對比:
-
屬于Collection架構;Hashtable
屬于Executor架構。ConcurrentHashMap
-
整個資料使用單鎖。在段級别上Hashtable
使用多個鎖(預設情況下為16),而不是對象級,即整體ConcurrentHashMap
。Map
-
鎖定僅适用于更新。在檢索的情況下,它允許完全并發,檢索反映最近完成的更新操作的結果。是以讀取可以非常快速地進行,而寫入是通過鎖定完成的。ConcurrentHashMap
-
不會抛出ConcurrentHashMap
,如果一個線程試圖另一種就是周遊它來修改它并不允許空值。ConcurrentModificationException
-
傳回ConcurrentHashMap
,它在并發修改時失敗 - 安全(即疊代器将複制内部資料結構)。Iterator
-
使用資料庫分片邏輯(ConcurrentHashMap
)稱為并發級别(Concurrency-Level),即将資料劃分為分片(片段),而不是對每個分片(分段)放置鎖定,而不是對整個資料(Segment<K, V>[] segments
)放置單個鎖定。預設值是16。Map
下面的比喻可以幫助你了解這個概念(而不是邏輯)
- 假設
并且Hashtable
是兩種類型的家庭。ConcurrentHashMap
-
鎖住家門。Hashtable
-
鎖定特定的房門而不是大門。ConcurrentHashMap
ConcurrentHashMap
對于線程應用程式更高效。
參考資料: https://howtodoinjava.com/core-java/multi-threading/best-practices-for-using-concurrenthashmap/
https://stackoverflow.com/questions/12646404/concurrenthashmap-and-hashtable-in-java
http://www.importnew.com/7010.html