Введение

В программировании идиомом инициализации по требованию держателя (дизайн-паттерна) является ленивый загруженный синглтон. Во всех версиях Java, идиома позволяет безопасную, высококонкурентную ленивую инициализацию статических полей с хорошей производительностью. public class Что-то { private Что-то {} private статический класс LazyHolder { static final Что-то INSTANCE = new Что-то ; } public static Что-то getInstance { return LazyHolder. ИНСТАНЦИЯ; } } Реализация идиома зависит от фазы инициализации выполнения в виртуальной машине Java (JVM), как указано в спецификации языка Java (JLS). Когда класс Something загружается JVM, класс проходит инициализацию. Поскольку у класса нет никаких статических переменных для инициализации, инициализация завершается тривиально. Статика определения класса LazyHolder в нем не инициализируется, пока JVM не определит, что LazyHolder должен быть выполнен. Статический класс LazyHolder выполняется только тогда, когда статический метод getInstance вызван на классе Something, и в первый раз, когда это произойдет, JVM загрузит и инициализирует класс LazyHolder. Инициализация класса LazyHolder приводит к инициализации статической переменной INSTANCE путем выполнения (частного) конструктора для внешнего класса Something. Поскольку фаза инициализации класса гарантирована JLS последовательностью, то есть неконкурентностью, никакой дальнейшей синхронизации не требуется в статическом методе getInstance во время загрузки и инициализации. И поскольку фаза инициализации записывает статическую переменную INSTANCE в последовательной операции, все последующие одновременные вызовы getInstance возвращают ту же самую правильно инициализированную INSTANCE без каких-либо дополнительных накладных затрат на синхронизацию.

Кавеат

Хотя реализация является эффективным кэшем "одиночного" стержня без накладных затрат на синхронизацию и лучшего исполнения, чем бесконтактная синхронизация, идиом может использоваться только тогда, когда конструкция Something гарантирована не провалится. В большинстве реализаций JVM, если конструкция Something не удается, последующие попытки инициализировать его из того же загрузчика классов приведут к сбою NoClassDefFoundError.