Recursive ConcurrentHashMap.computeIfAbsent() 调用永远不会终止。错误或“功能”?
前段时间,我在博客上写了一篇关于Java 8函数式方法的博客,它使用缓存和新的有用方法递归计算斐波那契数列:ConcurrentHashMap
computeIfAbsent()
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Test {
static Map<Integer, Integer> cache = new ConcurrentHashMap<>();
public static void main(String[] args) {
System.out.println(
"f(" + 8 + ") = " + fibonacci(8));
}
static int fibonacci(int i) {
if (i == 0)
return i;
if (i == 1)
return 1;
return cache.computeIfAbsent(i, (key) -> {
System.out.println(
"Slow calculation of " + key);
return fibonacci(i - 2) + fibonacci(i - 1);
});
}
}
我之所以选择并行性,是因为我正在考虑通过引入并行性来使此示例更加复杂(我最终没有这样做)。ConcurrentHashMap
现在,让我们将数字从 增加到 to 并观察会发生什么:8
25
System.out.println(
"f(" + 25 + ") = " + fibonacci(25));
该程序永远不会停止。在方法内部,有一个循环永远运行:
for (Node<K,V>[] tab = table;;) {
// ...
}
我正在使用:
C:\Users\Lukas>java -version
java version "1.8.0_40-ea"
Java(TM) SE Runtime Environment (build 1.8.0_40-ea-b23)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
那篇博客文章的读者马蒂亚斯(Matthias)也证实了这个问题(他实际上发现了这个问题)。
这很奇怪。我本来以为以下两个中的任何一个:
- 它的工作原理
- 它抛出一个
ConcurrentModificationException
但只是永不停止?这似乎很危险。这是一个错误吗?还是我误解了一些合同?