單例模式幾種安全的實現

 

單例的應用場景:java

須要頻繁的建立和銷燬對象的、建立對象時耗時過多或者消耗資源過多可是又常常用到的對象、工具類對象或數據庫或文件的對象。數據庫

當對象含有可改變的狀態時(更精確的說就是在實際應用中該狀態會改變),則用多例。安全

 

1、懶漢式,線程安全的實現函數

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

 

這雖然是線程安全的,可是效率低。還有一些比較常犯的錯誤,不加同步限制的,不作舉例。工具

 

2、餓漢式,線程安全spa

1.構造器私有化線程

2.類的內部建立對象code

3.像外部暴露一個靜態的公共方法。getInstance對象

 

優勢:在類裝載的時候就完成了實例化。避免了線程同步問題。blog

缺點:沒有達到Lazy Loading(懶加載)的效果,若是歷來沒使用過這個類,就會形成內存的浪費。

public class Singleton{
  //類加載時就初始化
  private static final Singleton instance = new Singleton();

  private Singleton(){}

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

可是要是明確要求是須要懶加載的,這個就不行的

 

第二種寫法,在類的靜態代碼塊中建立實例:

public class Singleton { //1.構造函數私有化
    private Singleton() { } //2.在本類的內部建立對象實例
    private static Singleton instance; static { instance = new Singleton(); } //3.提供靜態方法,返回實例對象
    public static Singleton getInstance() { return instance; } }

 

 

3、靜態內部類

我比較傾向於使用靜態內部類的方法,這種方法也是《Effective Java》上所推薦的。

public class Singleton { 
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

 

 

4、枚舉

用枚舉寫單例實在太簡單了!這也是它最大的優勢。下面這段代碼就是聲明枚舉實例的一般作法。

public enum EasySingleton{
INSTANCE;
}

 

建立enum時,編譯器會自動爲咱們生成一個繼承自java.lang.Enum的類,咱們上面的enum能夠簡單看做:

class Type extends Enum{ public static final Type A; public static final Type B; ... }

 demo:

public enum SingleEnum { INSTANCE; private static String[] strings = {"1", "2"}; public String[] getStrings() { return strings; } }

 

5、雙重檢測

 

//雙重檢查
public class Singleton {
private static volatile Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }

這個代碼只在第一次,兩個線程不能同時執行synchronized方法,可是,後面install不爲空後,instance == null就直接pass掉了。volatile的做用理解是instance = new Singleton當即到內存中生效。

相關文章
相關標籤/搜索