単例パターンのいくつかの書き方

3488 ワード

もっと読む
単一の例モードとは、簡単に言えば、アプリケーション全体において、1つのクラスだけのインスタンスが存在することを保証することである.SpringにおけるIOC構成のように、beanの実装はデフォルトでは一例モードです.
 単例の4つの書き方:
1.餓漢式の一例
//   
public class Singleton{
  //1.            ,                 
  private static final Singletion instance= new Singleton();
  //2.       ,                    
  private Singleton{}
  //3.                
  private static Singletion getInstance(){
    return instance;
  }
}
  長所:この書き方はスレッドの安全です.
  短所:初期化クラスと作成対象のオーバーヘッドが増加します.
 
2.怠け者タイプ
public class Singleton {
  //1.                
 private static Singleton instance = null;
  // 2.       ,           
  private Singleton{}
  //3.               ,        synchronized       
 public static synchronized Singleton getInstance() {
  if (instance == null)
   instance = new Singleton(); // lazy load
  return instance;
 } 
}
特典:遅延ロードは、使用時のみ初期化します.
問題:同期ロック粒度はマルチスレッドで取得するとブロックが発生し、ロック競争による性能オーバーヘッドが増大します.
 
3.ダブルチェックロック
public class Singleton { 
  //1.volatile     
 private static volatile Singleton instance = null;
  // 2.       ,           
  private Singleton{}
 public static Singleton getInstance() { 
     //3.instance  volatile                        
   if (instance == null) {// double check (jdk1.5+)
      //4.synchronized        ,                
      //5. instance = new Singletion(),         
      //   1).         2).       3).  instance           
      //6.    cpu   ,JMM        ,instance  2,3         
      //       instance  null,               (     )
   synchronized (Singleton.class)
    if (instance == null){
     instance = new Singleton();
        }
      }
  return instance;   
 } 
} 
利点:マルチスレッドが同期同期ロックのためにオーバーヘッドを低減し、同期同期同期保証モジュールが実行する原子性を低減するために、Volatile保証の実例が見られます.
短所:同期ロックモジュール内部のメソッド体instance=new Singleton()原子的な操作ではない(count++も原子的な操作ではない)か、それともJITコンパイラがコードを並べ替えて対象の値が正しくない可能性がありますか?
 
4.静的内部類の書き方
public class Singleton { 
  //1.            
 private static class Holder { // lazy class
  static final Singleton instance = new Singleton();
 }
  //2.        
  private Singleton(){ } 
  //3.        
 public static Singleton getInstance() {
  return Holder.instance;   
 } 
} 
 利点:スレッドが安全で、使用時に初期化されます.上記の3つの方法より優れています.
 
5.単例 列挙の書き方
 
public enum SingletonEnum {

    instance;
    /*
     * do something
     */
    public void doSomething(){
        System.out.println("do something");
    }
}
 
 
 
つまり、怠け者、悪漢、ダブルチェックロック、静的内部類、列挙.悪い男:クラスをロードする時にインスタンスを作成するので、スレッドの安全(複数のクラスのLoaderが存在する場合は例外).欠点は延長で読み込めないことです.怠け者:ロックをかけないとマルチスレッド同期ができませんが、効率が低下します.長時間ローディングが利点です.ダブルチェックロック:面倒ですが、現在のJavaメモリモデルでは必ずしも全部使用されていません.いくつかのプラットフォームとコンパイラは間違っています.instance=new Singletion()このコードは異なるコンパイラ上での挙動と実現方法が予測できないからです.静的内部クラス:遅延負荷、メモリオーバヘッドを低減します.使う時にロードするので、静的なfieldは一例の種類でロードする時にすぐメモリのpermantに入って永遠に回収の欠点が得られないことを免れました.列挙:良いです.マルチスレッドの同期問題を避けるだけでなく、アンチプログレッシブの新たなオブジェクト作成を防ぐこともできます.しかし、このような特性を失ってしまいました.負荷が遅くなりません.使う人が少なすぎます.
 
参考できる:
http://www.tuicool.com/articles/NVza2am