HashTable和HashMap的區別是,HashTable在操做table的方法上加入synchronized關鍵字,使得線程安全。實現方式和HashMap相似,可是HashTable沒有處理在某個槽下的值太多,鏈表過長的狀況。java
有序,二叉搜索樹,使用紅黑樹。使用key進行比較,或者傳入的比較器。方法containsKey、get、put和remove的時間複雜度是log(n)。數組
LinkedHashMap保存了元素的插入順序,在遍歷時會遵循插入的順序。而HashMap遍歷時,順序是按照table的順序,依次遍歷每個槽中的鏈表,因此順序和插入順序徹底不一樣。 安全
LinkedHashMap在Node上加上了before
和after
屬性用以構建保持原順序的雙向鏈表。 併發
LinkeHashMap能夠設置參數,使其從插入順序變爲訪問順序。 工具
LinkedHashMap基於HashMap,它本身的任務主要是維護保持順序的雙向鏈表。佈局
java.util.concurrent;線程
ConcurrentHashMap提供了一個高效的、線程安全的訪問和更新HashMap的方式。較之HashTable,它沒有提供在整個table上的鎖,同步方式粒度更細。code
看網上資料,舊版本的ConcurrentHashMap採用了分段的策略進行同步。Hash步驟以下:內存
全部併發訪問ConcurrentHashMap的線程會在每一個segment上同步,因此線程能夠並行的訪問不一樣的segment,減少了同步的粒度。 rem
可是,在1.8中,使用的是sun.misc.Unsafe
工具。它的做用有:
ConcurrentHashMap對table的操做所有由sun.misc.Unsafe來完成:
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) { return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE); } static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i, Node<K,V> c, Node<K,V> v) { //c表示舊值 //v表示新值 //更新前會驗證舊值是否變化,若是變化說明期間被其它線程修改,則修改失敗 //外部使用該方法通常會使用一個循環,以屢次重試 return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v); } static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) { U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v); }
能夠簡單的理解爲上述方法是原子性的,對目標數據所在的內存位置進行了加鎖,整個操做過程當中,對該部份內存的讀、寫不會受其它線程的影響。可見,該方法的併發實現粒度更細。
還有一點須要注意,在併發操做時,可能會出現有的線程開始擴張或縮小table,可是有的線程卻試圖操做table的狀況。由於搬遷table上元素的過程比較耗時,因此,其它線程發現該table正在重建,會先將操做table的事情日後放一放,而是轉頭去幫助搬遷table,等table搬遷完畢再繼續本身的活。