Синглтон ленивый против нетерпеливого создания
Если одноэлемент реализован следующим образом,
class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
Как эта реализация отличается от ленивого подхода к инициализации?
В этом случае экземпляр будет создан при загрузке класса, а сам класс будет загружен только при первом активном использовании (например, Singleton.getInstance() не тогда, когда вы объявляете, например, Singleton singleton = null;)
Даже при ленивом подходе к инициализации экземпляр создается при вызове getInstance()
Мне что-то не хватает?
Ответы
Ответ 1
Вы можете также вызвать любые другие статические методы или статические переменные-члены для загрузки экземпляра singleton.
class Logger {
private static Logger instance = new Logger();
public static String LOG_LINE_SEPERATOR =
System.getProperty("line.separator");
public static Logger getInstance() {
return instance;
}
public static String logPattern() {
return null;
}
}
...
Logger.LOG_LINE_SEPERATOR; // load Logger instance or
Logger.logPattern(); // load Logger instance
Ответ 2
При ленивой инициализации вы создаете экземпляр только тогда, когда это необходимо, а не при загрузке класса. Так вы избежите ненужного создания объекта. При этом есть и другие вещи, которые следует учитывать. При ленивой инициализации вы предоставляете открытый API для получения экземпляра. В многопоточной среде это создает проблемы, чтобы избежать ненужного создания объекта. Вы помещаете блоки синхронизации, которые создают ненужную блокировку для проверки уже созданного объекта. Таким образом, это становится проблемой производительности в этом случае.
Так что, если вы уверены, что создание вашего объекта не будет занимать значительную память и почти всегда будет использоваться в вашем приложении, тогда его полезно создавать при статической инициализации. Также, пожалуйста, не забудьте сделать ваш экземпляр окончательным в этом случае, так как он гарантирует, что создание объекта отражается правильно и полностью в основной памяти, что важно в многопоточной среде.
Пожалуйста, обратитесь к этому руководству от IBM по делу о многопоточной среде Singleton+ Lazy Loading+
=============== Редактировать 09/09/2018 ====================
Вы также должны посмотреть на создание объекта по шаблону здесь.
Ответ 3
По причинам, которые вы упомянули, это просто более сложный способ сделать то же самое, что и
enum Singleton {
INSTANCE;
}
Использование ленивой инициализации полезно только в том случае, если вы обеспокоены тем, что класс может быть инициализирован, но вы не хотите загружать синглтон в этой точке. Для большинства ситуаций это уже убивает.
Примечание. Просто ссылка на класс не инициализирует класс.
например. Скажем, у вас плохо написанный класс, который не может быть инициирован до тех пор, пока не будет установлено какое-либо условие. В этом случае n
должно быть отличным от нуля.
public class Main {
public static void main(String ... args) {
Class c= LazyLoaded.class;
System.out.println(c);
}
static class LazyLoaded {
static int n = 0;
static {
System.out.println("Inverse "+1000/n);
}
}
}
печатает
class Main$LazyLoaded
Ответ 4
Прежде всего, одноэлементный шаблон используется. То, что вы действительно хотите сделать, если вы хотите "одно из чего-то", - объявить его синглом в вашей выборке DI. Это эффективно управляемый конфигурацией синглтон и освобождает опции для инъекции макетов для правильного тестирования.
Почему не ленивая нагрузка? Если ваш класс не имеет массивную процедуру инициализации в конструкции (которую я бы утвердил, это также анти-шаблон), нет никакой пользы и большого количества недостатков для ленивой загрузки. Вы просто добавляете сложность и, возможно, нарушаете свою программу, если это не сделано правильно. Правильный способ (если нужно) - использовать идиому Инициализации по требованию.
Ответ 5
Для ленивой загрузки экземпляра синглтона я использую как показано ниже.
class Singleton {
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance() {
if(null==instance){
synchronized(Singleton.class){
if(null==instance){
instance = new Singleton();
}
}
}
return instance;
}
}
Ответ 6
Загрузка Eager в шаблоне Singleton - это не процесс, в котором нам нужно инициализировать объект Singleton во время запуска приложения, а не по требованию, и сохранять его готовым в памяти для использования в будущем. Преимущества использования Eager Loading в шаблоне разработки Singleton состоят в том, что CLR (Common Language Runtime) позаботится об инициализации объекта и безопасности потока. Это означает, что нам не потребуется явно писать какой-либо код для обработки безопасности потоков в многопоточной среде.
Ленивая или отложенная загрузка - это шаблон проектирования, или вы можете сказать, что это концепция, которая обычно используется для задержки инициализации объекта до точки, в которой он необходим. Таким образом, основная цель отложенной загрузки - загрузить объект по требованию, или вы можете сказать объект при необходимости. Самый важный момент, о котором вам нужно помнить, это то, что вам нужно использовать отложенную загрузку, когда стоимость создания объекта очень высока, а также использование этого объекта очень редко. Ленивая загрузка улучшает производительность приложения, если оно используется должным образом.
пожалуйста, обратитесь к следующим учебным пособиям по точечной сети, где вы можете найти наглядные примеры того и другого.
https://dotnettutorials.net/lesson/lazy-vs-eager-loading-chsrap/