Chronicle Map für Java: Komplettleitfaden mit Beispielen
Chronicle Map ist eine hochperformante, off-heap (außerhalb des Heap) Implementierung von ConcurrentMap für Java, entwickelt von Chronicle Software. Im Gegensatz zu standardmäßigen HashMap oder ConcurrentHashMap, die Daten im JVM-Heap speichern, platziert Chronicle Map Daten direkt im Arbeitsspeicher außerhalb des verwalteten Heaps. Dies vermeidet den Overhead der Garbage Collection (GC) und sorgt für vorhersagbare Latenzen, selbst bei der Verarbeitung großer Datenmengen (Gigabyte und Terabyte).
Diese Bibliothek ist ideal für Szenarien, die eine niedrige Latenz, hohen Durchsatz und die Verarbeitung von Daten erfordern, die sich nicht auf die GC-Pausenzeit auswirken sollen. Typische Anwendungen sind: Finanzsysteme (Handelsplattformen), Caching, Echtzeitsysteme, Sitzungsspeicher sowie alle Anwendungen, bei denen eine deterministische Leistung wichtig ist. Chronicle Map unterstützt den Multithread-Zugriff, die Serialisierung von Schlüsseln und Werten und kann für Persistenz (Datenspeicherung auf der Festplatte) konfiguriert werden.
In diesem Artikel gehen wir detailliert auf die Installation, die wichtigsten Methoden ein, zeigen viele praktische Beispiele und geben Tipps zur Leistungsoptimierung. Am Ende können Sie Chronicle Map sicher in Ihren Java-Projekten einsetzen.
1. Installation
Chronicle Map wird über Maven Central vertrieben. Fügen Sie für die Verwendung in Ihrem Projekt die folgende Abhängigkeit in Ihre pom.xml-Datei (Maven) ein:
<dependency>
<groupId>net.openhft</groupId>
<artifactId>chronicle-map</artifactId>
<version>3.25ea0</version> <!-- Überprüfen Sie die aktuelle Version auf Maven Central -->
</dependency>
Wenn Sie Gradle verwenden, fügen Sie die folgende Zeile in Ihre build.gradle ein:
implementation 'net.openhft:chronicle-map:3.25ea0'
2. Schnellstart – Minimales Arbeitsbeispiel
Erstellen wir eine einfache Map, die Paare aus "Benutzername" (String) und "Anzahl der Anmeldungen" (Long) speichert:
import net.openhft.chronicle.map.ChronicleMap;
public class QuickStart {
public static void main(String[] args) {
// ChronicleMap konfigurieren und erstellen
try (ChronicleMap<String, Long> loginCountMap = ChronicleMap
.of(String.class, Long.class)
.name("login-counts")
.averageKey("user123")
.averageValue(1000L)
.entries(10_000)
.create()) {
// Werte einfügen
loginCountMap.put("alice", 42L);
loginCountMap.put("bob", 15L);
// Werte abrufen
System.out.println("Alice Logins: " + loginCountMap.get("alice"));
// Vorhandenen Wert aktualisieren
loginCountMap.put("alice", 43L);
// Über alle Einträge iterieren
loginCountMap.forEach((key, value) ->
System.out.println(key + ": " + value));
}
}
}
averageKey() und averageValue() helfen Chronicle Map, den Speicher effizient zu verwalten, indem sie einen typischen Schlüssel und Wert angeben. Dies ist entscheidend für die Leistung.3. Wichtige Methoden im Überblick
Chronicle Map implementiert das java.util.concurrent.ConcurrentMap-Interface und bietet daher alle Standardmethoden. Darüber hinaus gibt es einige spezifische Methoden für die erweiterte Nutzung.
3.1 Standard-Methoden (ConcurrentMap)
| Methode | Beschreibung |
|---|---|
put(K key, V value) |
Fügt ein Schlüssel-Wert-Paar ein oder überschreibt einen vorhandenen Wert. |
get(Object key) |
Gibt den Wert für den angegebenen Schlüssel zurück oder null, wenn der Schlüssel nicht existiert. |
remove(Object key) |
Entfernt das Schlüssel-Wert-Paar und gibt den zugehörigen Wert zurück. |
containsKey(Object key) |
Prüft, ob ein bestimmter Schlüssel in der Map vorhanden ist. |
size() |
Gibt die Anzahl der Einträge in der Map zurück. |
clear() |
Entfernt alle Einträge aus der Map. |
3.2 Chronicle Map-spezifische Methoden
| Methode | Beschreibung |
|---|---|
putIfAbsent(K key, V value) |
Fügt das Paar nur ein, wenn der Schlüssel noch nicht vorhanden ist. Gibt den vorhandenen Wert zurück oder null. |
replace(K key, V oldValue, V newValue) |
Ersetzt den Wert nur, wenn der aktuelle Wert dem erwarteten oldValue entspricht. |
computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) |
Berechnet den Wert nur, wenn der Schlüssel nicht vorhanden ist. Dies ist eine atomare Operation. |
forEach(BiConsumer<? super K, ? super V> action) |
Führt die angegebene Aktion für jeden Eintrag in der Map aus. |
4. Fortgeschrittene Konfiguration und Persistenz
Chronicle Map kann so konfiguriert werden, dass Daten automatisch auf der Festplatte gespeichert werden. Dies ist nützlich, um den Zustand zwischen Neustarts der Anwendung zu erhalten.
import net.openhft.chronicle.map.ChronicleMap;
import java.io.File;
public class PersistentMapExample {
public static void main(String[] args) {
// Persistente Map mit Datei-Backing
try (ChronicleMap<Integer, String> persistentMap = ChronicleMap
.of(Integer.class, String.class)
.name("my-persistent-map")
.averageKey(100)
.averageValue("Ein durchschnittlicher Wert")
.entries(1000)
.createPersistedTo(new File("meine-daten.db"))) {
persistentMap.put(1, "Erster Eintrag");
persistentMap.put(2, "Zweiter Eintrag");
// Nach einem Neustart der Anwendung sind die Daten noch vorhanden
System.out.println("Wert für Schlüssel 1: " + persistentMap.get(1));
}
}
}
5. Leistungstipps und Best Practices
- Durchschnittliche Schlüssel-/Wertgrößen angeben: Verwenden Sie immer
averageKey()undaverageValue(), um die Speichernutzung zu optimieren. - Anzahl der Einträge schätzen: Geben Sie mit
entries()eine realistische Obergrenze für die erwartete Anzahl von Einträgen an, um unnötige Speicherzuweisungen zu vermeiden. - Kleine Schlüssel bevorzugen: Chronicle Map arbeitet am effizientesten mit kleinen, primitiven Schlüsseln (z. B.
intoderlong). - Vermeiden Sie häufige Größenänderungen: Eine einmal erstellte Map kann ihre Größe nicht dynamisch ändern. Planen Sie die Kapazität daher im Voraus.
- Nutzen Sie die atomaren Operationen: Methoden wie
computeIfAbsentundreplacesind effizienter als separateget- undput-Aufrufe in einer Multithread-Umgebung.
6. Fazit
Chronicle Map ist eine leistungsstarke und flexible Lösung für Java-Entwickler, die eine hochperformante, off-heap ConcurrentMap benötigen. Mit ihrer Fähigkeit, GC-Pausen zu minimieren und vorhersagbare Latenzen zu liefern, ist sie ideal für anspruchsvolle Anwendungen im Finanzwesen, Echtzeit-Caching und andere latenzkritische Systeme. Die einfache Installation über Maven oder Gradle und die vertraute API machen den Einstieg leicht. Experimentieren Sie mit den verschiedenen Konfigurationsmöglichkeiten, um die optimale Leistung für Ihren spezifischen Anwendungsfall zu erzielen.
Auch in der Bibliothek
Konfiguration von PHP-Anwendungen: Bibliotheken und Werkzeuge für flexible Einstellungen
TypeScript-Standardbibliothek: Vollständiger Überblick für Entwickler
Eloquent ORM für PHP: Vollständige Anleitung mit Beispielen
Retrofit für Kotlin: Vollständiger Leitfaden mit Beispielen