Hashtable HashMap ConcurrentHashMap 源碼分析

1.Hashtable與HashMap區別比較

先來講說這二者之間的不一樣:java

   1.Hashtable 是JDK1.2出現的, 父類繼承Dictionary 實現的是Map, HashMap父類是AbstractMap實現的Map 數組

public class Hashtable extends Dictionary implements Map
public class HashMap   extends AbstractMap implements Map

 

  2. Hashtable中的方法都是同步的, HashMap中的方法都是非同步的, 安全

      因此從性能上來講HashMap的效率比Hashtable快,  那麼若是在多線程併發的環境下,HashMap如何實現同步處理 多線程

      能夠經過 :  併發

  • Collections.synchronizedMap();

       來實現線程同步, 看下synchronizedMap內部實現:源碼分析

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
    return new SynchronizedMap<>(m);
}

private static class SynchronizedMap<K,V>
    implements Map<K,V>, Serializable {
    private static final long serialVersionUID = 1978198479659022715L;

    private final Map<K,V> m;     // Backing Map
    final Object      mutex;        // Object on which to synchronize

    SynchronizedMap(Map<K,V> m) {
        if (m==null)
            throw new NullPointerException();
        this.m = m;
        mutex = this;
    }
}    

    SynchronizedMap(Map<K,V> m, Object mutex) {
        this.m = m;
        this.mutex = mutex;
    }

    

    3.Hashtable中key和value都不能爲null, 在HashMap中, key能夠爲null,但這樣的健值只有一個, Hashtable源代碼:性能

  • public Object put(Object key, Object value) {
        // Make sure the value is not null
        if (value == null) throw new NullPointerException();
    }

     

     4. 二者遍歷的方式的內部實現不一樣, HashMap使用了Iterator, Hashtable使用了Enumeration的方式this

     5. 哈希值的使用不一樣, Hashtable直接使用對象的hashcode, HashMap從新計算hash值spa

     6. HashTable中hash數組默認大小爲11, 增長的方式是old*2+1,  HashMap數組的默認大小是16, 並且必定是2的指數     線程

    

      那麼接下來咱們來分析一下HashMap的內部結構:

      HashMap是一個數組和鏈表的組合體, 內部以下圖:


      源代碼分析: 

public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

             

        當往HashMap中put元素的時候,先根據key的hash值獲得這個元素在數組中的位置(即下標),而後就能夠把這個元素放到對應的位置中了。若是這個元素所在的位子上已經存放有其餘元素了,那麼在同一個位子上的元素將以鏈表的形式存放,新加入的放在鏈頭,最早加入的放在鏈尾

2.HashMap與ConcurrentHashMap源碼分析

前面咱們有說到,HashMap不是線程安全的, 那麼在多線程環境下, 咱們應該如何保證線程安全呢, 在JDK1.5以後咱們引入ConcurrentHashMap類:

public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
        implements ConcurrentMap<K, V>, Serializable {
}

  那麼ConcurrentHashMap是具體如何實現線程安全的,從源代碼中能夠看出它引入了一個叫「分段鎖」的概念,具體能夠理解成將Map劃分紅N個小的Hashtable, 根據key.hashCode()來決定把key放到哪一個HashTable中

在ConcurrentHashMap中,就是把Map分紅N個Segment,put和get的時候, 根據key.hashCode() 算出放到哪一個Segment中   

public V put(K key, V value) {
    Segment<K,V> s;
    if (value == null)
        throw new NullPointerException();
    int hash = hash(key);
    int j = (hash >>> segmentShift) & segmentMask;
    if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
         (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment
        s = ensureSegment(j);
    return s.put(key, hash, value, false);
}

public V get(Object key) {
    Segment<K,V> s; // manually integrate access methods to reduce overhead
    HashEntry<K,V>[] tab;
    int h = hash(key);
    long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
    if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
        (tab = s.table) != null) {
        for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile
                 (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
             e != null; e = e.next) {
            K k;
            if ((k = e.key) == key || (e.hash == h && key.equals(k)))
                return e.value;
        }
    }
    return null;
}

  以上就是ConcurrentHashMap的工做機制, 經過把整個Map劃分爲N個Segment,能夠提供相同的線程安全,效率提高N倍,默認提高16倍

相關文章
相關標籤/搜索