Как создать потокобезопасный Singleton в Java?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Существует несколько способов создания потокобезопасного Singleton:
-
Eager Initialization (ранняя инициализация):
public class Singleton { private static final Singleton INSTANCE = new Singleton(); // Создается при загрузке класса private Singleton() {} // Приватный конструктор public static Singleton getInstance() { return INSTANCE; } }Простой и потокобезопасный, но объект создается даже если не будет использован.
-
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; } }Безопасно, но может быть неэффективно из-за избыточной синхронизации при каждом вызове.
-
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гарантирует корректную видимость инициализации объекта между потоками. -
Using
Enum:public enum Singleton { INSTANCE; // Единственный экземпляр // Дополнительные методы и поля public void doSomething() { // ... } }Самый простой и надежный способ с точки зрения потокобезопасности и предотвращения проблем с десериализацией. Java гарантирует, что enum-константы инициализируются только один раз.