29

私はシングルトン、特にシングルトンの遅延初期化と熱心な初期化に関していくつかの調査を行っていました。

熱心な初期化の例:

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 が実際に使用されたときにのみ実行されます。これにより、遅延インスタンス化が処理され、スレッドセーフであることが保証されます。

これは正しいです?

4

5 に答える 5

25

あなたの 2 番目のコード スニペットは、私の意見では、シングルトンをスレッドセーフに遅延初期化する最良の方法です。実はパターン名が付いている

オンデマンド初期化ホルダーイディオム

使用することをお勧めします。

于 2013-04-03T16:03:06.857 に答える
9

あなたの最初のデザインは実際には怠け者です。考えてみてください。インスタンスは、クラスが初期化されたときにのみ作成されます。クラスは、メソッドが呼び出されたときにのみ初期化されますgetSingleton()[1]。したがって、インスタンスは要求されたときにのみ作成されます。つまり、遅延作成されます。

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

于 2013-04-03T16:35:23.953 に答える
3

2 番目のものは読みやすさの点で非常に悪く、最初のものは適しています。この記事をご覧ください。ダブルチェックロックに関するものですが、シングルトンのマルチスレッドに関する幅広い情報も提供します。

于 2013-04-03T16:01:28.730 に答える
1

最善の方法は、実際にはEnum Wayを使用することです。

public enum Singleton {
    INSTANCE;
    public void execute (String arg) {
            //... perform operation here ...
    }
}
于 2013-04-03T16:00:20.300 に答える