Storicamente, l'inizializzazione pigra è stata introdotta per ottimizzare l'uso delle risorse, quando un oggetto viene creato solo quando è realmente necessario. Inizialmente, era importante quando si lavorava con oggetti pesanti, connessioni, cache o nella realizzazione di complessi pattern (ad esempio, Singleton).
Il problema è che se si creano tutte le risorse subito, si possono spendere più memoria, tempo e potenza anche quando l'oggetto non è necessario. L'inizializzazione pigra risolve la questione della «creazione ritardata».
La soluzione è di solito implementata con un controllo: se l'oggetto non è ancora stato creato, lo creiamo, altrimenti restituiamo quello esistente.
Esempio di codice:
public class LazyHolder { private Resource resource; public Resource getResource() { if (resource == null) { resource = new Resource(); } return resource; } }
In condizioni multithreading è necessaria la sincronizzazione.
Caratteristiche chiave:
Il Double-Checked Locking è un'implementazione affidabile per l'inizializzazione pigra di Singleton?
Solo a partire da Java 5, poiché prima il memory model non lo garantiva. È necessario utilizzare la parola chiave volatile per il campo risorsa.
private volatile Resource resource; public Resource getResource() { if (resource == null) { synchronized(this) { if (resource == null) { resource = new Resource(); } } } return resource; }
Ha senso fare l'inizializzazione pigra per oggetti leggeri?
In genere, no. È meglio creare oggetti "leggeri" immediatamente, per non ridurre la leggibilità del codice e non complicarlo con logica superflua.
Funziona l'inizializzazione pigra durante la serializzazione degli oggetti?
Non sempre. Durante la serializzazione potrebbe essere ripristinato uno stato "vecchio", oppure potrebbe essere necessaria logica aggiuntiva in readObject().
In un servizio ad alto carico, un pool speciale di oggetti veniva analizzato pigro, ma non era sincronizzato. Due thread inizializzavano simultaneamente l'oggetto, portando a perdite di memoria e errori imprevedibili.
Pro:
Contro:
In una grande web app, l'analisi si connette solo tramite una chiamata API attraverso un oggetto proxy inizializzato pigro con double-checked locking.
Pro:
Contro: