簡體   English   中英

Hashtable和Collections.synchronizedMap(HashMap)之間的區別

[英]Difference between Hashtable and Collections.synchronizedMap(HashMap)

據我所知, java.util.Hashtable同步java.util.Map接口中的每個方法,而Collections.synchronizedMap(hash_map)返回一個包裝器對象,其中包含將調用委托給實際hash_map同步方法(如果我,請更正我)我錯了。

我有兩個問題:

  1. 它與同步每個方法和包裝類有什么區別? 有哪些方案可以選擇其中一種?

  2. 當我們做Collections.synchronizedMap(hash_table)時會發生什么? 這是否等於簡單地使用普通的java.util.Hashtable

我在兩個類的實現中可以找到的另一個區別如下:

Hashtable類的所有方法都已同步,即鎖定是在方法級別完成的,因此可以說互斥鎖始終處於Hashtable對象( this )級別。

•方法Collections.synchronizedMap(Map)返回SynchronizedMap的實例,它是Collections類的內部類。 此類在具有互斥鎖的Synchronized塊中具有其所有方法。 不同之處在於互斥體。 內部類SynchronizedMap有兩個構造函數,一個只將Map作為參數,另一個以MapObject (互斥)作為參數。 如果通過使用一個只傳遞一個的第一個構造函數的默認Mapthis是作為一個互斥。 但是,允許開發人員傳遞另一個互斥對象作為第二個參數,通過該對象, Map方法上的鎖定僅在該Object ,因此比Hashtable更少限制。

•因此, Hashtable使用方法級別同步,但Collections.synchronizedMap(Map)為開發人員提供了使用Synchronized塊鎖定所提供的互斥鎖的靈活性。

以下是我從一些(希望是正確的)研究得到的答案:

  1. 兩者都提供相同程度的同步。 如果您要通過Collections.synchronized包裝Hashtable ,那么您將具有相同的度數,但具有另一個冗余層,具有同步性。

  2. HashtableCollections.synchronizedMap(HashMap)之間的主要區別存在於API級別。 由於Hashtable是Java遺留代碼的一部分,因此您將看到Hashtable API已得到增強,可實現Map接口,從而成為Java集合框架的一部分。 這意味着,如果你包Hashtable通過Collections.synchronizedMap()包裹的API Hashtable將成為受限於Map API。 因此,如果Hashtable的API包含在您的行為定義中,那么它顯然會被更改/限制。

出現在Java類庫中的第一個關聯集合類是Hashtable,它是JDK 1.0的一部分。 Hashtable提供了一個易於使用,線程安全的關聯映射功能,它當然很方便。 然而,線程安全是有代價的 - 所有Hashtable方法都是同步的。 那時,無競爭同步具有可測量的性能成本。 HashMap的后續版本HashMap作為JDK 1.2中Collections框架的一部分出現,它通過提供一個非同步的基類和一個同步的包裝器Collections.synchronizedMap來解決線程安全問題。 將基本功能與線程安全性Collections.synchronizedMap分離,允許需要同步的用戶擁有它,但不需要它的用戶不必為此付費。

Hashtable和synchronizedMap同步的簡單方法 - 同步Hashtable或同步Map包裝器對象上的每個方法 - 有兩個主要缺陷。 這是可伸縮性的障礙,因為一次只有一個線程可以訪問哈希表。 同時,提供真正的線程安全性是不夠的,因為許多常見的復合操作仍然需要額外的同步。 雖然諸如get()和put()之類的簡單操作可以安全地完成而無需額外的同步,但是有幾種常見的操作序列,例如迭代或put-if-absent,它們仍然需要外部同步以避免數據爭用。

以下鏈接是源代碼,包含更多信息: 並發集合類

差異並非都在明顯的API級別,並且在實現級別存在許多細微之處。 例如, Hashtable不會使HashMap高級重新計算提供的密鑰的哈希碼,從而減少哈希沖突。 另一方面, Hashtable#hashCode()避免了自引用哈希表的無限遞歸,以允許“具有自引用哈希表的某些1.1時代的applet工作”。

但是,一般而言,不應指望Hashtable接收除基本正確性和向后兼容性之外的任何進一步改進或改進。 它被認為是Java深層歷史遺留下來的遺物。

需要注意的另一個不同點是HashTable不允許空鍵或值,而HashMap允許一個空鍵和任意數量的空值。 由於synchronizedMap是HashMap的包裝器,因此它對null鍵和值的行為與HashMap相同。

陳述明顯(或明顯錯誤)的風險並非如此

同步包裝器將自動同步(線程安全性)添加到任意集合

http://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html並繼續說

以這種方式創建的集合與正常同步的集合(例如Vector)一樣具有線程安全性。

您可能希望看到此線程有關HashMaps和並發的問題 - Hashmap並發問題 (或者您可能已經非常了解它們)。 一個很好的例子是:

HashMap不會滿足您描述的條件。 由於更新地圖的過程不是原子的,因此您可能會遇到無效狀態的地圖。 多次寫入可能會使其處於損壞狀態。 ConcurrentHashMap(1.5或更高版本)可以滿足您的需求。

https://stackoverflow.com/a/1003071/201648

我想在“我什么時候應該使用它”方面,我傾向於使用需要並發的同步集合,否則你可能會為自己創造更多的工作(見下文)。

在改變行為方面

如果使用顯式迭代器,則必須從synchronized塊中調用迭代器方法。 不遵循此建議可能會導致不確定的行為

在提供的(Oracle)鏈接上使用同步會產生更多后果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM