6

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

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

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

提前致谢

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

返回此映射中包含的键的集合视图。集合由地图支持,因此对地图的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射(通过迭代器自己的删除操作除外),则迭代的结果是不确定的。该集合支持元素移除,即通过 Iterator.remove、Set.remove、removeAll retainAll 和 clear 操作从映射中移除相应的映射。它不支持 add 或 addAll 操作。

4

2 回答 2

6

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

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

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

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

于 2009-03-27T12:08:51.197 回答
0

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

于 2009-03-27T12:08:36.847 回答