java中的懒惰单例初始化

时间:2018-01-11 19:48:12

标签: java singleton

我们都知道这个古老的着名的lazy-init单身成语:

public class Singleton {
    private static volatile Singleton instance;

    private Singleton()
    {
        // init...
    }

    public static Singleton getInstance()
    {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }

        return instance;
    }
}

但是,下面的习惯用法本质上也是懒惰的,因为只有在第一次访问类时,实例才是init,由类加载器处理:

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

    private Singleton()
    {
        // init..
    }

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

所以问题是,为什么我们要使用第一个例子而不是第二个例子呢? (并不是说使用spring等框架来管理对象的生命周期更好。)

即使您在另一个类中持有对单例的引用,例如:

public class Holder {
   private int member1;
   private int member2;
   private Singleton myService = Singleton.getInstance();

}

无论我们采用哪种方法

,都会在加载Holder类时创建单例

任何见解? 感谢

1 个答案:

答案 0 :(得分:0)

这样的事情怎么样?

public class Singleton {
    ...
    public static int getSomeStaticInfo() { return 42; }
    ...
} 

public class Holder {
    private int member1;
    private int member2 = Singleton.getSomeStaticInfo();
    private Singleton myService;

    public void init() {
        myService = Singleton.getInstance();
    }
}

初始化单例时的行为在两个版本之间有所不同。这是版本1表现正确的(就我们说"懒惰"时所要求的)行为。仅仅因为你加载了这个类,并不意味着你想要它被初始化。