Historisch wurde Lazy Initialization eingeführt, um den Ressourcenverbrauch zu optimieren, indem ein Objekt nur dann erstellt wird, wenn es wirklich benötigt wird. Ursprünglich war dies wichtig beim Arbeiten mit schweren Objekten, Verbindungen, Caches oder bei der Implementierung komplexer Muster (zum Beispiel Singleton).
Das Problem besteht darin, dass man, wenn man alle Ressourcen sofort erstellt, unnötig Speicher, Zeit und Ressourcen verschwenden kann, selbst wenn das Objekt nicht benötigt wird. Lazy Initialization löst das Problem der 'verzögerten' Erstellung.
Die Lösung wird normalerweise durch eine Überprüfung implementiert: Wenn das Objekt noch nicht erstellt wurde, erstellen wir es, andernfalls geben wir das vorhandene zurück.
Beispielcode:
public class LazyHolder { private Resource resource; public Resource getResource() { if (resource == null) { resource = new Resource(); } return resource; } }
Unter Mehrfachthreads sind Synchronisationsmechanismen erforderlich.
Wesentliche Merkmale:
Ist Double-Checked Locking eine zuverlässige Implementierung für Lazy Initialization von Singleton?
Nur seit Java 5, da vorher das Memory Model dies nicht garantierte. Es ist notwendig, das Schlüsselwort volatile für das Ressourcenfeld zu verwenden.
private volatile Resource resource; public Resource getResource() { if (resource == null) { synchronized(this) { if (resource == null) { resource = new Resource(); } } } return resource; }
Hat es Sinn, Lazy Initialization für leichte Objekte zu verwenden?
In der Regel nicht. Es ist besser, "leichte" Objekte sofort zu erstellen, um die Lesbarkeit des Codes nicht zu verringern und sie nicht mit überflüssiger Logik zu komplizieren.
Funktioniert Lazy Initialization bei der Serialisierung von Objekten?
Nicht immer. Bei der Serialisierung kann der "alte" Zustand wiederhergestellt werden, oder es kann zusätzliche Logik in readObject() erforderlich sein.
In einem High-Load-Service wurde ein spezieller Pool von Objekten lazy geparsed, war aber nicht synchronisiert. Zwei Threads initialisierten gleichzeitig das Objekt, was zu Speicherlecks und unvorhersehbaren Fehlern führte.
Vorteile:
Nachteile:
In einer großen Webanwendung wird die Analyse nur über einen API-Aufruf über ein lazy initialisierendes Proxy-Objekt mit Double-Checked Locking aktiviert.
Vorteile:
Nachteile: