Java単例モードSingleton

2754 ワード

朝から大通りが工事中で、バタバタして眠れない.単例モードについては、最初は簡単だと思って、ずっとこう書いていました.
public class Singleton{
     public static Singleton instance = null;

     private Singleton(){
     }

     public static Singleton getInstance(){
          if(instance == null){
               instance = new Singleton();
          }
          return instance;
     }
}

ちょうど最近Java関連のマルチスレッドを見ていて、同時です.ネットでこの質問をした人もいました.上のこの方法はスレッドが安全ではありません!だから変えましょう.synchronizedを加えればいいじゃないか.
public synchronized static Singleton getInstance(){
     if(instance == null){
          instance = new Singleton();
     }
     return instance;
}

これでいいに違いない.しかし、唯一面倒なのはSingletonを大量に呼び出すことです.getInstance()の場合、パフォーマンスに問題がある場合があります.さらに変更して、中に鍵をかけます.
public static Singleton getInstance(){
     if(instance == null){
          synchronized(Singleton.class){
               if(instance == null){
                    instance = new Singleton();
               }
          }
     }
     return instance;
}

Instanceがnullの条件にロックを加えると、ずっと速くなります.そして中にはもう一つの判断が必要だ.これで他の県城が再呼び出しされたときにinstanceが初期化されてnewは不要になりました...ネット上ではこれをdouble-checked lockingと呼んでいます.他に方法はありますか?いっそクラスを宣言するときに直接初期化すればいいんじゃない!?すると、次のようなものがありました.
 
public class Singleton{
     public static final Singleton INSTANCE = new Singleton();

     private Singleton(){
     }

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

これでいいです.しかし、ネット上では、この疲れた初期化の消費が少ないときにこのように使うことができると言われています.PS:finalを加えると可変ではありません.最後に探したトラブルは、ウィキペディア(https://en.wikipedia.org/wiki/Singleton_pattern).前の例がすべてあることを発見して、しかも2つのもっと狂燥な例を提供しました.例1:
public class Singleton{
     public static class SingletonHolder(){
          private static final Singleton INSTANCE = new Singleton();
     }

     private Singleton(){
     }

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

これはJava仮想マシンが内部クラスをこのように処理する際にスレッドの安全を保証するためらしい.また、すべてのバージョンのJVMで決定できるという.例2:
public enum Singleton{
     INSTANCE;

     public void doSomeThing(){
          // ...
     }
}

ちょっと简単すぎて....なんとエンムを使っています!!!そして使う時はそのままINSTANCEでいいです!!!しかし、JDK 5以上でサポートされるようで、サポートの原因は簡単です.JDK 5以降の列挙でオブジェクトを作成するのはスレッドが安全です...『Effect Java』ではこうやってやってました...