Деякий час тому я писав у блозі про функціональний спосіб 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
бо думав зробити цей приклад ще більш витонченим, запровадивши паралелізм (чого зрештою не зробив).
Тепер давайте збільшимо число від 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)
Матіас, читач цієї публікації в блозі, також підтвердив проблему (він насправді її знайшов) .
Це дивно. Я б очікував будь-якого з наступних двох:
- Це працює
- Це кидає a
ConcurrentModificationException
Але просто ніколи не зупиняючись? Це здається небезпечним. Це помилка? Або я неправильно зрозумів якийсь контракт?