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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM