调试JDK源码-Hashtable实现原理以及线程安全的原因
調試JDK源碼-一步一步看HashMap怎么Hash和擴容
調試JDK源碼-ConcurrentHashMap實現原理
調試JDK源碼-HashSet實現原理
調試JDK源碼-調試JDK源碼-Hashtable實現原理以及線程安全的原因
?
Hashtable是線程安全的,我們從源碼來分析
?
代碼很簡單
Hashtable<String, String> ht = new Hashtable<String, String>();ht.put("111", "http://blog.csdn.net/unix21/");ht.put("222", "www.csdn.net");ht.put("333", <a target=_blank href="http://www.java.com">www.java.com</a>);
?
注釋寫的很好,生成一個新的,空的hashtable,使用默認的capacity容量為11,factor增長因子為0.75
?
這一步開始初始化
下一步就完成了實例化
?
Entry是一個靜態嵌套類
/*** Hashtable bucket collision list entry*/private static class Entry<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Entry<K,V> next;protected Entry(int hash, K key, V value, Entry<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}@SuppressWarnings("unchecked")protected Object clone() {return new Entry<>(hash, key, value,(next==null ? null : (Entry<K,V>) next.clone()));}// Map.Entry Opspublic K getKey() {return key;}public V getValue() {return value;}public V setValue(V value) {if (value == null)throw new NullPointerException();V oldValue = this.value;this.value = value;return oldValue;}public boolean equals(Object o) {if (!(o instanceof Map.Entry))return false;Map.Entry<?,?> e = (Map.Entry<?,?>)o;return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&(value==null ? e.getValue()==null : value.equals(e.getValue()));}public int hashCode() {return hash ^ Objects.hashCode(value);}public String toString() {return key.toString()+"="+value.toString();}}
?
其實就是因為這個put方法是synchronized的所以可以保證其線程安全
?
?
算出hash碼,然后算出在默認長度11下的index索引是4
?
默認entry為空直接跳到addEntry(hash, key, value, index)
?
addEntry方法體內,一開始modCount=0
?
下一步由于count =0? > ?threshold=8
?
生成一個新的Entry
?
新的節點掛在tab[4]上,然后count++。
?
回到put函數,至此一個完整的put就完成了。
?
第二次put,生成的index是7
?
哈希沖突
注意這段代碼,其實就是判斷是否出現hash沖突了
Entry<K,V> entry = (Entry<K,V>)tab[index];for(; entry != null ; entry = entry.next) {if ((entry.hash == hash) && entry.key.equals(key)) {V old = entry.value;entry.value = value;return old;}}
?知道了hashtable默認的長度是11,那么我們就可以制造一個會產生哈希沖突的數據集就可以了
Hashtable<String, String> ht = new Hashtable<String, String>();for (int i = 0; i < 20; i++) {ht.put((char) (i + 65) + (char) (i + 66) + (char) (i + 67) + "", i + ">>>http://blog.csdn.net/unix21/");}
?
經過幾次put之后,終于產生了一次哈希沖突,這次的索引是10,而tab[10]已經有值。
產生沖突有2個原因一個是因為相同的key必然會產生相同的索引。還有一種就是不同的值產生哈希沖突了。
所以這里先判斷是不是相同的key導致的。
?
進入addEntry方法
?
之前的沖突節點一并傳入,被掛在新節點后面也就是其next下
?
回到addEntry,可以看到新的節點以及掛在tab[10].next下了。
總結
以上是生活随笔為你收集整理的调试JDK源码-Hashtable实现原理以及线程安全的原因的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 调试JDK源码-HashSet实现原理
- 下一篇: 《异步处理在分布式系统中的优化作用》学习