1. 程式人生 > >java中那些類是執行緒安全的?

java中那些類是執行緒安全的?

Java中各種集合(字串類)的執行緒安全性!!!

 

一、概念:

  • 執行緒安全:就是當多執行緒訪問時,採用了加鎖的機制;即當一個執行緒訪問該類的某個資料時,會對這個資料進行保護,其他執行緒不能對其訪問,直到該執行緒讀取完之後,其他執行緒才可以使用。防止出現數據不一致或者資料被汙染的情況。
  • 執行緒不安全:就是不提供資料訪問時的資料保護,多個執行緒能夠同時操作某個資料,從而出現數據不一致或者資料汙染的情況。
  • 對於執行緒不安全的問題,一般會使用synchronized關鍵字加鎖同步控制。
  • 執行緒安全 工作原理: jvm中有一個main memory物件,每一個執行緒也有自己的working memory,一個執行緒對於一個變數variable進行操作的時候, 都需要在自己的working memory裡建立一個copy,操作完之後再寫入main memory。 
    當多個執行緒操作同一個變數variable,就可能出現不可預知的結果。 
    而用synchronized的關鍵是建立一個監控monitor,這個monitor可以是要修改的變數,也可以是其他自己認為合適的物件(方法),然後通過給這個monitor加鎖來實現執行緒安全,每個執行緒在獲得這個鎖之後,要執行完載入load到working memory 到 use && 指派assign 到 儲存store 再到 main memory的過程。才會釋放它得到的鎖。這樣就實現了所謂的執行緒安全。

 

二、執行緒安全(Thread-safe)的集合物件:

  • Vector 
  • HashTable
  • StringBuffer

 

三、非執行緒安全的集合物件:

  • ArrayList :
  • LinkedList:
  • HashMap:
  • HashSet:
  • TreeMap:
  • TreeSet:
  • StringBulider:

 

四、相關集合物件比較:

  • Vector、ArrayList、LinkedList: 
    1、Vector: 
    Vector與ArrayList一樣,也是通過陣列實現的,不同的是它支援執行緒的同步,即某一時刻只有一個執行緒能夠寫Vector,避免多執行緒同時寫而引起的不一致性,但實現同步需要很高的花費,因此,訪問它比訪問ArrayList慢。 
    2、ArrayList: 

    a. 當操作是在一列資料的後面新增資料而不是在前面或者中間,並需要隨機地訪問其中的元素時,使用ArrayList效能比較好。 
    b. ArrayList是最常用的List實現類,內部是通過陣列實現的,它允許對元素進行快速隨機訪問。陣列的缺點是每個元素之間不能有間隔,當陣列大小不滿足時需要增加儲存能力,就要講已經有陣列的資料複製到新的儲存空間中。當從ArrayList的中間位置插入或者刪除元素時,需要對陣列進行復制、移動、代價比較高。因此,它適合隨機查詢和遍歷,不適合插入和刪除。 
    3、LinkedList: 
    a. 當對一列資料的前面或者中間執行新增或者刪除操作時,並且按照順序訪問其中的元素時,要使用LinkedList。 
    b. LinkedList是用連結串列結構儲存資料的,很適合資料的動態插入和刪除,隨機訪問和遍歷速度比較慢。另外,他還提供了List介面中沒有定義的方法,專門用於操作表頭和表尾元素,可以當作堆疊、佇列和雙向佇列使用。

    Vector和ArrayList在使用上非常相似,都可以用來表示一組數量可變的物件應用的集合,並且可以隨機的訪問其中的元素。

 

  • HashTable、HashMap、HashSet: 
    HashTable和HashMap採用的儲存機制是一樣的,不同的是: 
    1、HashMap: 
    a. 採用陣列方式儲存key-value構成的Entry物件,無容量限制; 
    b. 基於key hash查詢Entry物件存放到陣列的位置,對於hash衝突採用連結串列的方式去解決; 
    c. 在插入元素時,可能會擴大陣列的容量,在擴大容量時須要重新計算hash,並複製物件到新的陣列中; 
    d. 是非執行緒安全的; 
    e. 遍歷使用的是Iterator迭代器;

    2、HashTable: 
    a. 是執行緒安全的; 
    b. 無論是key還是value都不允許有null值的存在;在HashTable中呼叫Put方法時,如果key為null,直接丟擲NullPointerException異常; 
    c. 遍歷使用的是Enumeration列舉;

    3、HashSet: 
    a. 基於HashMap實現,無容量限制; 
    b. 是非執行緒安全的; 
    c. 不保證資料的有序;

 

  • TreeSet、TreeMap: 
    TreeSet和TreeMap都是完全基於Map來實現的,並且都不支援get(index)來獲取指定位置的元素,需要遍歷來獲取。另外,TreeSet還提供了一些排序方面的支援,例如傳入Comparator實現、descendingSet以及descendingIterator等。 
    1、TreeSet: 
    a. 基於TreeMap實現的,支援排序; 
    b. 是非執行緒安全的;

    2、TreeMap: 
    a. 典型的基於紅黑樹的Map實現,因此它要求一定要有key比較的方法,要麼傳入Comparator比較器實現,要麼key物件實現Comparator介面; 
    b. 是非執行緒安全的;

 

  • StringBuffer和StringBulider: 
    StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字元陣列儲存字串。

    1、在執行速度方面的比較:StringBuilder > StringBuffer ; 
    2、他們都是字串變數,是可改變的物件,每當我們用它們對字串做操作時,實際上是在一個物件上操作的,不像String一樣建立一些物件進行操作,所以速度快; 
    3、 StringBuilder:執行緒非安全的; 
    4、StringBuffer:執行緒安全的; 


  
  對於String、StringBuffer和StringBulider三者使用的總結: 
   1.如果要操作少量的資料用 = String 
   2.單執行緒操作字串緩衝區 下操作大量資料 = StringBuilder 
   3.多執行緒操作字串緩衝區 下操作大量資料 = StringBuffer