Не буду рассказывать, что такое singleton и для чего он нужен. Расскажу про то, как его писать.

Всегда склонялся к варианту double check, но после статьи про текущую модель памяти в java, мир для меня перестал быть прежним. Оказывается, volatile довольно затратная операция и немного лучше synchronized. Наилучшим же вариантом с ленивой инициализацией будет следующий код:

Этот вариант является thread-safe и lazy.

Потокобезопасный потому что java гарантирует что final поля будут проинициализированы только один раз и никакой потом не увидит null значения.

Ленивым этот вариант является потому что java инициализирует static поля у класса только в момент обращения к данному классу. Класс SingletonCreator ни в каких местах не доступен, кроме метода getInstance.