天天看點

單例設計模式singleton

簡單引入

單例設計模式作為最簡單,最常用的設計模式。一般是這兩中寫法,這兩種寫法教科書所謂的标準寫法,但是實際上存在不少問題。後面介紹标準寫法,以規避這些問題。

1.懶漢式:

/**
   * 問題在于,當多線程工作的時候,如果有多個線程同時運作到if (instance ==
   * null),都判斷為null,那麼兩個線程就各自會建立一個執行個體——這樣一來,就不是單例了。
   */
class Singleton {

  private Singleton() {
  };

  private static Singleton s;

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

}
      

2.惡漢式

class Singleton {
  private Singleton() {
  }

  private static Singleton singleton = new Singleton();

  public static Singleton getInstance() {
    return singleton;
  }

}      

标準寫法

改變懶漢式1.

(規避線程安全問題)加上 synchronized修飾方法即可

class Singleton {

  private Singleton() {
  };

  private static Singleton s;

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

}
      

改變懶漢式2. 雙重檢查 Double-Check』寫法

1.第一個if 隻有instance為null的時候,才進入synchronized的代碼段——大大減少了幾率。

2.第二個if 是為了防止可能出現多個執行個體的情況。

class DoubleCheck {

  private DoubleCheck() {
  }

  private static DoubleCheck dCheck;

  public static DoubleCheck getInstance() {
    if (dCheck == null) {
      synchronized (DoubleCheck.class) {
        if (dCheck == null) {
          dCheck = new DoubleCheck();
        }
      }
    }
    return dCheck;
  }

}
      

改變懶漢式2.之終極版 防止指令重排列 volatile

不知道原子操作,與指令重排的建議複習下

class DoubleCheck2 {
  private DoubleCheck2() {
  }

  private static volatile DoubleCheck2 sCheck;

  public static DoubleCheck2 getInstance() {
    if (sCheck == null) {
      synchronized (DoubleCheck2.class) {
        if (sCheck == null) {
          sCheck = new DoubleCheck2();
        }
      }
    }
    return sCheck;
  }

}
      

1.惡漢式:

/*
   * 缺點也就隻是餓漢式單例本身的缺點所在了——由于INSTANCE的初始化是在類加載時進行的,而類的加載是由ClassLoader來做的,
   * 是以開發者本來對于它初始化的時機就很難去準确把握:
   * 
   * 可能由于初始化的太早,造成資源的浪費 如果初始化本身依賴于一些其他資料,那麼也就很難保證其他資料會在它初始化之前準備好。
   */
class Singleton {
  private Singleton() {
  }

  private static final Singleton singleton = new Singleton();

  public static Singleton getInstance() {
    return singleton;
  }

}
      

由于靜态内部類實作

class innerSingleton {
  private innerSingleton() {

  }

  private static class SingletonHolder {
    private static final innerSingleton SINGLETON = new innerSingleton();
  }

  public static innerSingleton getInstance() {
    return SingletonHolder.SINGLETON;
  }

}