Почему шаблон считается нарушенным? Мне это нравится? Есть идеи?
public static Singleton getInst() {
if (instace == null) createInst();
return instace;
}
private static synchronized createInst() {
if (instace == null) {
instace = new Singleton();
}
}
На первый взгляд все выглядит нормально, но у этого метода есть много тонких проблем, и его обычно следует избегать. Например, рассмотрим следующую последовательность событий:
Этого можно было бы избежать, используя ключевое слово volatile для правильной обработки одноэлементных экземпляров
Проблема заключается в следующем: ваша JVM может изменить порядок вашего кода, а поля не всегда одинаковы для разных потоков. Взгляните на это: http://www.ibm.com/developerworks/java/library/j-dcl.html. Использование ключевого слова volatile должно исправить это, но оно не работает до версии java 1.5.
В большинстве случаев блокировка с одиночной проверкой более чем достаточно быстра, попробуйте следующее:
// single checked locking: working implementation, but slower because it syncs all the time
public static synchronized Singleton getInst() {
if (instance == null)
instance = new Singleton();
return instance;
}
Также взгляните на эффективную java, где вы найдете отличную главу по этой теме.
Подводя итог: Не выполняйте блокировку с двойной проверкой, есть идомы получше.
Я не знаю, сломано ли это, однако это не самое эффективное решение из-за довольно дорогой синхронизации. Лучшим подходом было бы использование «идиомы держателя инициализации по запросу», которая загружает ваш синглтон в память при первом запросе, как следует из названия, таким образом, ленивая загрузка. Самое большое преимущество, которое вы получаете с этой идиомой, заключается в том, что вам не нужно синхронизироваться, поскольку JLS гарантирует, что загрузка классов является последовательной.
Подробная запись в Википедии по этому вопросу: http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
Еще одна вещь, которую следует иметь в виду, это то, что с появлением сред внедрения зависимостей, таких как Spring и Guice, класс экземпляры создаются и управляются этими контейнерами, и при желании они предоставят вам синглтон, поэтому не стоит ломать голову над этим, если только вы не хотите научиться идеям, лежащим в основе шаблона, что полезно. Также обратите внимание, что синглтоны, предоставляемые этими контейнерами IOC, являются синглтонами для каждого экземпляра контейнера, но обычно у вас будет один контейнер IOC для каждого приложения, поэтому это не становится проблемой.
Это не ответ на ваш вопрос (другие уже ответили), но я хочу рассказать вам о своем опыте работы с синглтонами/ленивыми инициализированными объектами:
В нашем коде было несколько синглетонов . Однажды нам пришлось добавить параметр конструктора в один синглтон и возникла серьезная проблема, потому что конструктор этого синглтона вызывался на геттере. Были только следующие возможные решения:
Наконец, последний вариант был выходом. Теперь мы инициализируем все объекты при запуске приложения и передаем необходимые экземпляры (возможно, в виде небольшого интерфейса). Мы не пожалели об этом решении, потому что