Назад к вопросам
Middle
222
questionbank

Как создать потокобезопасный Singleton в Java?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Существует несколько способов создания потокобезопасного Singleton:

  1. Eager Initialization (ранняя инициализация):

    public class Singleton {
        private static final Singleton INSTANCE = new Singleton(); // Создается при загрузке класса
    
        private Singleton() {} // Приватный конструктор
    
        public static Singleton getInstance() {
            return INSTANCE;
        }
    }
    

    Простой и потокобезопасный, но объект создается даже если не будет использован.

  2. Lazy Initialization (отложенная инициализация) с использованием synchronized method:

    public class Singleton {
        private static Singleton instance;
    
        private Singleton() {}
    
        public static synchronized Singleton getInstance() { // Синхронизированный метод
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    Безопасно, но может быть неэффективно из-за избыточной синхронизации при каждом вызове.

  3. Lazy Initialization с использованием Double Checked Locking:

    public class Singleton {
        private static volatile Singleton instance; // Используем volatile
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (instance == null) { // Первый null-check (без блокировки)
                synchronized (Singleton.class) { // Блокировка
                    if (instance == null) { // Второй null-check (внутри блокировки)
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    Снижает избыточную синхронизацию. Использование volatile гарантирует корректную видимость инициализации объекта между потоками.

  4. Using Enum:

    public enum Singleton {
        INSTANCE; // Единственный экземпляр
    
        // Дополнительные методы и поля
        public void doSomething() {
            // ...
        }
    }
    

    Самый простой и надежный способ с точки зрения потокобезопасности и предотвращения проблем с десериализацией. Java гарантирует, что enum-константы инициализируются только один раз.