Vor einiger Zeit habe ich über eine Java 8-Methode zur rekursiven Berechnung von Fibonacci-Zahlen mit einem ConcurrentHashMap
Cache und der neuen, nützlichen computeIfAbsent()
Methode gebloggt :
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);
});
}
}
Ich habe mich entschieden, ConcurrentHashMap
weil ich daran gedacht habe, dieses Beispiel durch die Einführung von Parallelität (was ich am Ende nicht getan habe) noch komplexer zu machen.
Erhöhen wir nun die Anzahl von 8
bis 25
und beobachten, was passiert:
System.out.println(
"f(" + 25 + ") = " + fibonacci(25));
Das Programm wird nie angehalten. Innerhalb der Methode gibt es eine Schleife, die einfach für immer läuft:
for (Node<K,V>[] tab = table;;) {
// ...
}
Ich benutze:
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, ein Leser dieses Blogposts, bestätigte das Problem ebenfalls (er fand es tatsächlich) .
Das ist komisch. Ich hätte eine der folgenden beiden erwartet:
- Es klappt
- Es wirft ein
ConcurrentModificationException
Aber einfach nie aufhören? Das scheint gefährlich. Ist es ein Fehler? Oder habe ich einen Vertrag falsch verstanden?