繁体   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