1. 程式人生 > >ArrayList和Vector的區別,HashMap和Hashtable的區別以及執行緒安全的理解【轉】

ArrayList和Vector的區別,HashMap和Hashtable的區別以及執行緒安全的理解【轉】

http://www.cnblogs.com/xionglee/articles/1554701.html

就ArrayList與Vector主要從二方面來說.

一.同步性:Vector是執行緒安全的,也就是說是同步的,而ArrayList是執行緒序不安全的,不是同步的

二.資料增長:當需要增長時,Vector預設增長為原來一培,而ArrayList卻是原來的一半



就HashMap與HashTable主要從三方面來說。

一.歷史原因:Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map介面的一個實現

二.同步性:Hashtable是執行緒安全的,也就是說是同步的,而HashMap是執行緒序不安全的,不是同步的

三.值:只有HashMap可以讓你將空值作為一個表的條目的key或value

什麼是執行緒安全

       如果你的程式碼所在的程序中有多個執行緒在同時執行,而這些執行緒可能會同時執行這段程式碼。如果每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。

  或者說:一個類或者程式所提供的介面對於執行緒來說是原子操作或者多個執行緒之間的切換不會導致該介面的執行結果存在二義性,也就是說我們不用考慮同步的問題。

舉例

比如一個 ArrayList 類,在新增一個元素的時候,它可能會有兩步來完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。

  在單執行緒執行的情況下,如果 Size = 0,新增一個元素後,此元素在位置 0,而且 Size=1;

  而如果是在多執行緒情況下,比如有兩個執行緒,執行緒 A 先將元素存放在位置 0。但是此時 CPU 排程執行緒A暫停,執行緒 B 得到執行的機會。執行緒B也向此 ArrayList 新增元素,因為此時 Size 仍然等於 0 (注意哦,我們假設的是新增一個元素是要兩個步驟哦,而執行緒A僅僅完成了步驟1),所以執行緒B也將元素存放在位置0。然後執行緒A和執行緒B都繼續執行,都增加 Size 的值。

  那好,現在我們來看看 ArrayList 的情況,元素實際上只有一個,存放在位置 0,而 Size 卻等於 2。這就是“執行緒不安全”了。

在Hashtable中,所有涉及到更新其中存放的內容的方法都是同步的
如:
public synchronized Object put(Object key, Object value) {}
public synchronized Object get(Object key) {}
...

以此來保證Hashtable不會被多個執行緒同時更改

1.Hashtable基本上沒用了,用HashMap代替.
2.需要同步的話用Collections.synchronizedMap(new HashMap())。
3.即使同步了,也不一定是安全的,併發修改時仍然會出錯。

HashMap和HashTable的比較是Java面試中的常見問題,用來考驗程式設計師是否能夠正確使用集合類以及是否可以隨機應變使用多種思路解決問題。HashMap的工作原理、ArrayList與Vector的比較以及這個問題是有關Java 集合框架的最經典的問題。HashTable是個過時的集合類,存在於Java API中很久了。在Java 4中被重寫了,實現了Map介面,所以自此以後也成了Java集合框架中的一部分。HashTable和HashMap在Java面試中相當容易被問到,甚至成為了集合框架面試題中最常被考的問題,所以在參加任何Java面試之前,都不要忘了準備這一題。

  這篇文章中,我們不僅將會看到HashMap和HashTable的區別,還將看到它們之間的相似之處。

  HashMap和HashTable的區別

  HashMap和HashTable都實現了Map介面,但決定用哪一個之前先要弄清楚它們之間的分別。主要的區別有:執行緒安全性,同步(synchronization),以及速度。

  1. HashMap幾乎可以等價於HashTable,除了HashMap是非synchronized的,並可以接受null(HashMap可以接受為null的鍵值(key)和值(value),而HashTable則不行)。
  2. HashMap是非synchronized,而HashTable是synchronized,這意味著HashTable是執行緒安全的,多個執行緒可以共享一個HashTable;而如果沒有正確的同步的話,多個執行緒是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴充套件性更好。
  3. 另一個區別是HashMap的迭代器(Iterator)是fail-fast迭代器,而HashTable的enumerator迭代器不是fail-fast的。所以當有其它執行緒改變了HashMap的結構(增加或者移除元素),將會丟擲ConcurrentModificationException,但迭代器本身的remove()方法移除元素則不會丟擲ConcurrentModificationException異常。但這並不是一個一定發生的行為,要看JVM。這條同樣也是Enumeration和Iterator的區別。
  4. 由於HashTable是執行緒安全的也是synchronized,所以在單執行緒環境下它比HashMap要慢。如果你不需要同步,只需要單一執行緒,那麼使用HashMap效能要好過HashTable。
  5. HashMap不能保證隨著時間的推移Map中的元素次序是不變的。

  要注意的一些重要術語:

  1) sychronized意味著在一次僅有一個執行緒能夠更改HashTable。就是說任何執行緒要更新HashTable時要首先獲得同步鎖,其它執行緒要等到同步鎖被釋放之後才能再次獲得同步鎖更新HashTable。

  2) Fail-safe和iterator迭代器相關。如果某個集合物件建立了Iterator或者ListIterator,然後其它的執行緒試圖“結構上”更改集合物件,將會丟擲ConcurrentModificationException異常。但其它執行緒可以通過set()方法更改集合物件是允許的,因為這並沒有從“結構上”更改集合。但是假如已經從結構上進行了更改,再呼叫set()方法,將會丟擲IllegalArgumentException異常。

  3) 結構上的更改指的是刪除或者插入一個元素,這樣會影響到map的結構。

  我們能否讓HashMap同步?

  HashMap可以通過下面的語句進行同步:

  Map m = Collections.synchronizeMap(hashMap);

  結論

  HashTable和HashMap有幾個主要的不同:執行緒安全以及速度。僅在你需要完全的執行緒安全的時候使用HashTable,而如果你使用Java 5或以上的話,請使用ConcurrentHashMap吧。