我对这两个集合在多线程环境中的行为方式感到非常困惑。
哈希表是同步的,这意味着没有 2 个线程会同时更新它的值,对吧?
我对这两个集合在多线程环境中的行为方式感到非常困惑。
哈希表是同步的,这意味着没有 2 个线程会同时更新它的值,对吧?
查看ConcurrentHashMap的线程安全映射。
它们提供了 HashTable 的所有功能,性能非常接近 HashMap。
通过不使用映射范围的锁来获得性能,该集合默认维护一个包含 16 个锁的列表,每个锁用于锁定映射的单个存储桶。您甚至可以配置存储桶的数量 :) 调整这可以根据您的数据提高性能。
我不能推荐足够多的 Java Concurrency in Practice by Brian Goetz http://jcip.net/
每次阅读它,我仍然会学到一些新东西。
确切地说,HashTable 是同步的,这意味着在多线程环境中使用它是安全的(许多线程访问同一个 HashTable)如果两个线程尝试同时更新哈希表,其中一个必须等待另一个线程完成他的更新。
HashMap 不同步,因此速度更快,但在多线程环境中可能会出现问题。
还要注意 Hashtable 和Collections.synchronizedMap
仅对单个操作是安全的。任何涉及多个键或需要原子检查的操作都不会如此,并且需要额外的客户端锁定。
例如,您不能在没有附加锁定的情况下编写以下任何方法:
交换两个不同键的值:swapValues(Map, Object k1, Object k2)
将参数附加到键处的值:appendToValue(Map, Object k1, String suffix)
是的,所有这些都包含在 JCIP 中 :-)
是的,所有方法都是原子完成的,但 values() 方法不是(请参阅文档)。
Paul 比我更快地向你推荐了 java.util.concurrent 包,它为多线程环境提供了非常精细的控制和数据结构。
哈希表是同步的,但它们是一个旧的实现,你几乎可以说它已被弃用。此外,它们不允许空键(也许也不是空值?不确定)。
一个问题是,虽然每个方法调用都是同步的,但大多数有趣的操作需要不止一个调用,因此您必须围绕多个调用进行同步。
通过调用 HashMap 可以获得类似级别的同步:
Map m = Collections.synchronizedMap(new HashMap());
它将映射包装在同步方法调用中。但这与 Hashtable 具有相同的并发缺点。
正如 Paul 所说,ConcurrentHashMaps 为线程安全映射提供了额外有用的原子更新方法。