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