遇到 ConcurrentHashMap
的奇怪行为:首先,多个线程使用 putIfAbsent()
和 remove( )
。一段时间后(几十秒甚至一分钟)另一个线程使用两种方法检查 map 是否为空:
- 调用
myMap.isEmpty()
方法 - 尝试查看迭代器中是否有任何条目:
myMap.entrySet().iterator().hasNext()
令人惊讶的是,这两种方法给出了不同的结果。 isEmpty()
返回 true
并且 iterator.hasNext()
紧随其后返回 true
。调用之间没有任何暂停,此时没有在 map 上执行写入操作。
请注意,根据日志,没有 isEmpty()
返回 false
和 iterator.hasNext()
返回 false
同时。所以总是 isEmpty()
方法没有“看到” map 中的任何条目。
想知道这是否是 ConcurrentHashMap
的预期行为。
文档指出:
Bear in mind that the results of aggregate status methods including size, isEmpty, and containsValue are typically useful only when a map is not undergoing concurrent updates in other threads. Otherwise the results of these methods reflect transient states that may be adequate for monitoring or estimation purposes, but not for program control.
这给出了这样的想法,即当没有正在进行的写操作时,size()
和 isEmpty()
等方法应该返回与映射的实际内容一致的值.
最佳答案
ConcurrentHashMap.getEntrySet()
的 javadoc 告诉您从集合中获得的迭代器弱一致性。
java.util.concurrent
包的 Javadoc 解释了“弱一致性”的含义:
... their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal:
- they may proceed concurrently with other operations
- they will never throw ConcurrentModificationException
- they are guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect any modifications subsequent to construction.
最后一个项目符号很重要。它告诉您迭代器是创建迭代器时映射中的内容的 View 。如果您随后更改 map 的内容,迭代器的内容不会更改。
关于java - ConcurrentHashMap 包含值,但 size() 方法返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36128804/