【问题标题】:Java ConcurentMap keySet() question when map is modified and iterating over keyset修改映射并迭代键集时的Java ConcurentMap keySet()问题
【发布时间】:2010-10-15 22:13:27
【问题描述】:

快速背景 我有一个并发映射,用于缓存一些经常更改的值(仍然值得在测试中缓存它们)。我想通过检查值中的过期时间定期从我的缓存中逐出项目。我正在使用 keySet() 方法获取对我所有键的引用,然后检查值,如果过期,我将其删除。在其他线程中,缓存不断被查询和更新(删除)。

从 keySet() 的 javadocs 中提到,如果在我迭代 keyset Set 时地图发生变化,结果是未定义的。显然,我想要一种定义的方式来处理这个问题,所以结果是有效的。将 Set 传递给 HashSet 然后迭代这个集合是否足够,因为我的理解是这个集合不会得到地图的支持,这是一种浪费内存的方式吗?任何想法表示赞赏。

不幸的是,我的 evictor 并不是从并发映射中删除项目的唯一方法,所以我说我需要在迭代之前将 keySet 复制到另一个 Set 是正确的。

提前致谢

编辑:原来我正在阅读 Map keySet() 方法的 javadocs,而不是 ConcurrentMap keySet()。谢谢我的坏:)

返回键的集合视图 包含在这张地图中。套装是 由地图支持,因此更改为 地图反映在集合中,并且 反之亦然。如果地图被修改 而对集合的迭代在 进展(除了通过 迭代器自己的删除操作), 迭代的结果是 不明确的。集合支持元素 删除,它删除 地图中的对应映射, 通过 Iterator.remove、Set.remove、 removeAll 保留全部,并清除 操作。它不支持 add 或 addAll 操作。

【问题讨论】:

    标签: java concurrency map


    【解决方案1】:

    您在使用the Java Concurrent HashMap 吗?从 keySet() 文档来看,它的行为方式似乎对您有用。

    返回此映射中包含的键的集合视图。集合由地图支持,因此对地图的更改会反映在集合中,反之亦然。该集合支持元素移除,即通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作从此映射中移除相应的映射。它不支持 add 或 addAll 操作。视图返回的迭代器是一个“弱一致”迭代器,它永远不会抛出 ConcurrentModificationException,并保证遍历迭代器构造时存在的元素,并且可能(但不保证)反映构造后的任何修改。

    即你可以删除东西,你应该没问题。

    如果您没有使用此实现,那么您使用的是哪个(以及为什么?不好笑,但知道您为什么做出这个选择会很有趣)

    【讨论】:

    • 非常感谢 Brian ye,我正在使用并发哈希图,但是在查看 javadocs 时正在阅读地图文档:) 谢谢一百万
    【解决方案2】:

    如果 LRU 缓存足够满足您的需求,请查看 LinkedHashMap — 它使实现 LRU 缓存变得简单,然后您可以通过调用 Collections.synchronizedMap 将结果包装成线程安全的。

    【讨论】:

      猜你喜欢
      • 2019-07-08
      • 2017-10-15
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-03
      相关资源
      最近更新 更多