1

我是 Java8 的新手,正在解决多个线程(~10)正在将值写入并发哈希映射的问题。我有另一个专用线程,它读取并发哈希映射中存在的所有值并返回它们(每 30 秒)。迭代 values() 方法的结果是在不获取并发修改异常的情况下获取结果的推荐方法吗?

注意:我完全可以获取过时的数据

我查看了官方文档,其中说:

检索操作一般不会阻塞,因此可能与更新操作重叠。检索反映了最近完成的更新操作在其开始时保持的结果。对于 putAll 和 clear 等聚合操作,并发检索可能仅反映插入或删除某些条目。类似地,迭代器、拆分器和枚举返回反映哈希表在创建迭代器/枚举时或之后的某个时间点的状态的元素。它们不会抛出 ConcurrentModificationException。

但是 values() 方法的文档说:

返回此映射中包含的值的集合视图

下面的代码线程安全吗?

for (String name: myMap.values()) {
     System.out.println("name": + name);
}
4

1 回答 1

2

迭代方法的结果是values()在不获取结果的情况下获取结果的推荐方法ConcurrentModificationException吗?

是的。这是推荐的方式,你不会得到ConcurrentModificationException.

正如包级 javadoc 所述:

大多数并发 Collection 实现(包括大多数队列)也不同于通常的 java.util 约定,因为它们的 Iterators 和 Spliterators 提供弱一致而不是快速失败遍历:

  • 它们可能与其他操作同时进行
  • 他们永远不会扔ConcurrentModificationException
  • 它们保证遍历元素,因为它们在构造时就存在一次,并且可能(但不保证)反映构造后的任何修改。

下面的代码线程安全吗?

  for (String name: myMap.values()) {
       System.out.println("name": + name); 
  }

是的......有一些资格。

线程安全实际上意味着代码在多线程应用程序中按照其指定的行为工作。问题是您没有清楚地说明您期望代码实际做什么

我们可以说的是:

  1. 迭代将根据前面所述的保证查看值。
  2. 内存模型保证意味着不应该有任何带有陈旧值的令人讨厌的行为......除非您在将值对象放入映射后对其进行变异。(如果您这样做,则需要实现对象的方法以应对这种情况;例如,它们可能需要是synchronized。这对值没有实际意义String,因为它们是不可变的。)
于 2019-05-04T16:06:41.847 回答