1. 程式人生 > >java 收集2

java 收集2

曾經 UC 設計模式 計算 頭結點 lin code 通過 segment

推薦書:Java並發編程實戰、深入理解Java虛擬機、大話設計模式

HashMap的工作原理

HashMap與HashTable的區別。
1、HashMap是非線程安全的,HashTable是線程安全的。
2、HashMap的鍵和值都允許有null值存在,而HashTable則不行。
3、因為線程安全的問題,HashMap效率比HashTable的要高。

HashMap的實現機制:

    1. 維護一個每個元素是一個鏈表的數組,而且鏈表中的每個節點是一個Entry[]鍵值對的數據結構。
    2. 實現了數組+鏈表的特性,查找快,插入刪除也快。
    3. 對於每個key,他對應的數組索引下標是 int i = hash(key.hashcode)&(len-1);
    4. 每個新加入的節點放在鏈表首,然後該新加入的節點指向原鏈表首

HashMap基於hashing原理,我們通過put()和get()方法儲存和獲取對象。當我們將鍵值對傳遞給put()方法時,它調用鍵對象的hashCode()方法來計算hashcode,讓後找到bucket位置來儲存值對象。當獲取對象時,通過鍵對象的equals()方法找到正確的鍵值對,然後返回值對象。HashMap使用鏈表來解決碰撞問題,當發生碰撞了,對象將會儲存在鏈表的下一個節點中。 HashMap在每個鏈表節點中儲存鍵值對對象。

當兩個不同的鍵對象的hashcode相同時會發生什麽? 它們會儲存在同一個bucket位置的鏈表中。鍵對象的equals()方法用來找到鍵值對。

因為HashMap的好處非常多,我曾經在電子商務的應用中使用HashMap作為緩存。因為金融領域非常多的運用Java,也出於性能的考慮,我們會經常用到HashMap和ConcurrentHashMap。

HashMap不是線程安全的,往往在寫程序時需要通過一些方法來回避.其實JDK原生的提供了2種方法讓HashMap支持線程安全.

方法一:通過Collections.synchronizedMap()返回一個新的Map,這個新的map就是線程安全的. 這個要求大家習慣基於接口編程,因為返回的並不是HashMap,而是一個Map的實現.

方法二:重新改寫了HashMap,具體的可以查看java.util.concurrent.ConcurrentHashMap. 這個方法比方法一有了很大的改進.

HashMap,ConcurrentHashMap與LinkedHashMap的區別

  1. ConcurrentHashMap是使用了鎖分段技術技術來保證線程安全的,鎖分段技術:首先將數據分成一段一段的存儲,然後給每一段數據配一把鎖,當一個線程占用鎖訪問其中一個段數據的時候,其他段的數據也能被其他線程訪問
  2. ConcurrentHashMap 是在每個段(segment)中線程安全的
  3. LinkedHashMap維護一個雙鏈表,可以將裏面的數據按寫入的順序讀出

ConcurrentHashMap應用場景
1:ConcurrentHashMap的應用場景是高並發,但是並不能保證線程安全,而同步的HashMap和HashMap的是鎖住整個容器,而加鎖之後ConcurrentHashMap不需要鎖住整個容器,只需要鎖住對應的Segment就好了,所以可以保證高並發同步訪問,提升了效率。
2:可以多線程寫。
ConcurrentHashMap把HashMap分成若幹個Segmenet
1.get時,不加鎖,先定位到segment然後在找到頭結點進行讀取操作。而value是volatile變量,所以可以保證在競爭條件時保證讀取最新的值,如果讀到的value是null,則可能正在修改,那麽就調用ReadValueUnderLock函數,加鎖保證讀到的數據是正確的。
2.Put時會加鎖,一律添加到hash鏈的頭部。
3.Remove時也會加鎖,由於next是final類型不可改變,所以必須把刪除的節點之前的節點都復制一遍。
4.ConcurrentHashMap允許多個修改操作並發進行,其關鍵在於使用了鎖分離技術。它使用了多個鎖來控制對Hash表的不同Segment進行的修改。

ConcurrentHashMap能夠保證每一次調用都是原子操作,但是並不保證多次調用之間也是原子操作。
友情鏈接:Java集合—ConcurrentHashMap原理分析

實現多線程

有三種手段,一種是繼續Thread類,另外一種是實現Runable接口,還有就是實現Callable接口

抽象類和接口的區別

a.一個類只能繼承單個類,但是可以實現多個接口

b.抽象類中可以有構造方法,接口中不能有構造方法

c.抽象類中的所有方法並不一定要是抽象的,你可以選擇在抽象類中實現一些基本的方法。而接口要求所有的方法都必須是抽象的

d.抽象類中可以包含靜態方法,接口中不可以

e.抽象類中可以有普通成員變量,接口中不可以

java 收集2