单例模式,结合了延迟加载和线程安全

2022-09-01 13:10:02

我正在做一些关于单例的研究,特别是关于单例的懒惰与渴望初始化。

预先初始化的示例:

public class Singleton
{
    //initialzed during class loading
    private static final Singleton INSTANCE = new Singleton();

    //to prevent creating another instance of Singleton
    private Singleton(){}

    public static Singleton getSingleton(){
        return INSTANCE;
    }
}

但是如上所示,它是预先初始化和线程安全留给jvm,但现在,我希望有这个相同的模式,但具有惰性初始化。

所以我想出了这种方法:

public final class Foo {
    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }
    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }
    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }
}

如上图所示,自行

private static final Foo INSTANCE = new Foo(); 

仅在实际使用类 FooLoader 时执行,这会处理惰性实例化,并且是否保证是线程安全的。

这是正确的吗?


答案 1

在我看来,你的第二个代码片段是线程安全延迟初始化单例的最佳方式。它实际上有一个模式名称

按需初始化持有者成语

我建议你使用它。


答案 2

你第一次设计实际上是懒惰的。想想看,实例仅在类初始化时创建;仅当该方法称为 [1] 时,该类才会初始化。因此,仅当请求时才创建实例,即它是懒惰地创建的。getSingleton()

[1] http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1


推荐