66

スレッドセーフな遅延初期化を実現するための推奨されるアプローチは何ですか? 例えば、

// Not thread-safe
public Foo getInstance(){
    if(INSTANCE == null){
        INSTANCE = new Foo();
    }

    return INSTANCE;
}
4

12 に答える 12

65

シングルトンの場合、静的初期化のためにタスクを JVM コードに委任することによる洗練されたソリューションがあります。

public class Something {
    private Something() {
    }

    private static class LazyHolder {
            public static final Something INSTANCE = new Something();
    }

    public static Something getInstance() {
            return LazyHolder.INSTANCE;
    }
}

見る

http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom

Crazy Bob Lee のこのブログ投稿

http://blog.crazybob.org/2007/01/lazy-loading-singletons.html

于 2011-11-28T15:06:11.597 に答える
10

最も簡単な方法は、静的内部ホルダー クラスを使用することです。

public class Singleton {

    private Singleton() {
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }

    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }
}
于 2011-11-28T15:05:05.077 に答える
8
class Foo {
  private volatile Helper helper = null;
  public Helper getHelper() {
    if (helper == null) {
      synchronized(this) {
        if (helper == null) {
          helper = new Helper();
        }
      }
    }
  return helper;
}

これはダブルチェックと呼ばれます。これをチェックしてくださいhttp://jeremymanson.blogspot.com/2008/05/double-checked-locking.html

于 2011-11-28T15:00:22.380 に答える
0

synchronized適切なロックを使用してコードをブロックに入れます。他にも高度に専門的な手法がいくつかありますが、どうしても必要な場合以外は避けることをお勧めします。

staticまた、インスタンス メソッドを示す傾向がある SHOUTY ケースを使用しました。本当に静的な場合は、決して変更できないことを確認することをお勧めします。静的な不変を作成するだけでコストがかかる場合、クラスのロードはとにかく怠惰です。別の (おそらくネストされた) クラスに移動して、作成を可能な限り最後の瞬間まで遅らせることができます。

于 2011-11-28T15:01:06.263 に答える
0

あなたが達成しようとしているものに応じて:

すべてのスレッドで同じインスタンスを共有する場合は、メソッドを同期化できます。これで十分でしょう

スレッドごとに個別のインスタンスを作成する場合は、java.lang.ThreadLocal を使用する必要があります。

于 2011-11-28T15:01:18.393 に答える
-1

インスタンスを同期済みとして取得するメソッドを定義してみてください。

public synchronized Foo getInstance(){
   if(INSTANCE == null){
    INSTANCE = new Foo();
  }

  return INSTANCE;
 }

または変数を使用します。

private static final String LOCK = "LOCK";
public synchronized Foo getInstance(){
  synchronized(LOCK){
     if(INSTANCE == null){
       INSTANCE = new Foo();
     }
  }
  return INSTANCE;
 }
于 2011-11-28T15:04:52.787 に答える