Подтвердить что ты не робот

Синглтон ленивый против нетерпеливого создания

Если одноэлемент реализован следующим образом,

class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }
}

Как эта реализация отличается от ленивого подхода к инициализации? В этом случае экземпляр будет создан при загрузке класса, а сам класс будет загружен только при первом активном использовании (например, Singleton.getInstance() не тогда, когда вы объявляете, например, Singleton singleton = null;)

Даже при ленивом подходе к инициализации экземпляр создается при вызове getInstance()

Мне что-то не хватает?

4b9b3361

Ответ 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/