单例懒惰与渴望实例化

2022-09-01 04:34:55

如果单例实现如下,

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

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

此实现与惰性初始化方法有何不同?在这种情况下,实例将在加载类时创建,并且类本身仅在第一次活动使用时加载(例如,Singleton.getInstance() 而不是当您声明实例 Singleton singleton = null 时;)

即使使用惰性初始化方法,实例也是在调用 getInstance() 时创建的

我在这里错过了什么吗?


答案 1

使用延迟初始化,您仅在需要实例时才创建实例,而不是在加载类时。因此,您逃避了不必要的对象创建。话虽如此,还有其他事情需要考虑。在延迟初始化中,您提供一个公共 API 来获取实例。在多线程环境中,它带来了避免不必要的对象创建的挑战。你把同步块,这会导致不必要的锁定来检查已经创建的对象。因此,在这种情况下,它成为性能问题。

因此,如果您确定创建对象不会占用任何重要内存,并且几乎总是在应用程序中使用,那么在静态初始化中创建它是很好的。此外,在这种情况下,请不要忘记使您的实例最终确定,因为它可以确保对象创建正确并完整地反映到主内存中,这在多线程环境中非常重要。

请参考 IBM 关于 Singleton+ Lazy Loading+ 多线程环境案例的本教程

===============编辑于 09/09/2018=======================

您还应该在此处查看按需创建对象模式。


答案 2

您也可以调用任何其他静态方法或静态成员变量来加载单例实例。

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

推荐