Ответ
Lazy Singleton (Ленивая инициализация) — это вариант реализации паттерна Одиночка, при котором единственный экземпляр класса создается не при загрузке класса, а в момент первого вызова метода получения экземпляра (например, getInstance()).
Ключевое преимущество перед Eager Singleton:
- Экономия ресурсов: Экземпляр не создается, если он никогда не понадобится. Это критично, если инициализация объекта требует значительных ресурсов (память, процессорное время, подключение к БД).
Пример потокобезопасной реализации на Java с использованием synchronized:
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {
// Приватный конструктор
}
// Синхронизированный метод для потокобезопасности
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
Недостаток и улучшение:
- Производительность: Синхронизация всего метода
getInstance()создает накладные расходы при каждом вызове. -
Решение — Double-Checked Locking:
public class LazySingletonDCL { // volatile гарантирует видимость изменения instance всеми потоками private static volatile LazySingletonDCL instance; private LazySingletonDCL() {} public static LazySingletonDCL getInstance() { if (instance == null) { // Первая проверка (без блокировки) synchronized (LazySingletonDCL.class) { if (instance == null) { // Вторая проверка (под блокировкой) instance = new LazySingletonDCL(); } } } return instance; } }Альтернатива (рекомендуемая): Использование статического внутреннего класса (Initialization-on-demand holder idiom), которая является потокобезопасной и эффективной.
public class BillPughSingleton { private BillPughSingleton() {} private static class SingletonHolder { private static final BillPughSingleton INSTANCE = new BillPughSingleton(); } public static BillPughSingleton getInstance() { return SingletonHolder.INSTANCE; // Инициализация происходит здесь } }