單例模式

1.定義:確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例。

  單例模式的主要關鍵點:

   1>構造函數不能對外開放,一般爲private;

   2>通過一個靜態方法或者枚舉返回單例類對象。

   3>確保單例類的對象有且只有一個,尤其是在多線程環境下。

   4>確保單例類對象在反序列化時不會重新構建對象。

2.應用場景:創建一個對象需要消耗資源過多,如要訪問IO和數據庫等資源,這時就要考慮

  使用單例模式。

3.實現方式:

   1>餓漢式模式(在程序啓動或單例模式類被加載的時候,單例模式實例就已經被創建。)

public class Singleton {
    private static final Singleton mInstance = new Singleton();

    private Singleton() {
    }

    public static Singleton getmInstance() {
        return mInstance;
    }
}

    2>懶漢模式(當程序第一次訪問單例模式實例時才被創建。)(不建議使用)

    優點:單例只有在使用時才被實例化,在一定程度上節約了資源。

    缺點:第一次加載時需要及時進行實例化,反應稍慢,最大的問題是每次調用getInstance都進行

    同步,造成不必要的同步開銷。

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

    3>雙重檢查鎖機制(雙重檢查鎖定模式首先驗證鎖定條件(第一次檢查),只有通過鎖定條件驗證才真正

  的進行加鎖邏輯並再次驗證條件(第二次檢查)。)(使用比較多)

  優點:資源利用率高,第一次執行getInstance時單例對象纔會被實例化,並且能夠保證線程安全和單例

  對象初始化後調用getInstance不再進行同步鎖。

  缺點:除此加載時反應稍慢,由於java內存模型的原因偶爾會失敗,在高併發環境下也有一些缺陷,雖

  然概率小。

public class Singletons {
    private static Singletons sInstance=null;
    private Singletons(){}
    public void doSomething(){
        System.out.println("do sth.");
    }
    public static Singletons getsInstance(){
        if (sInstance==null){
            synchronized (Singletons.class){
                if (sInstance==null){
                    sInstance=new Singletons();
                }
            }
        }
        return sInstance;
    }
}

  4>靜態內部類單例模式(通過使用一個私有的靜態內部類,來存儲外部類的單例)(重點推薦)

  誕生前景:DCL雖然在一定程度上解決了資源消耗、多餘的同步、線程安全等問題,但還是在

  某些情況下會出現失效問題,該問題被稱爲雙重檢查鎖(DCL)失效。

  優點:第一次加載Singleton類時並不會初始化sInstance,只有在第一次調用Singleton的getInstance

  方法時纔會導致sInstance被初始化。因此第一次調用getInstance方法會導致虛擬機加載SingletonHolder

  類,這種方式不僅能確保線程安全,也能保證單例對象的唯一性,同時延遲了單例的實例化。

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

  5>枚舉單例

    優點:簡便、線程安全、任何情況下都是一個單例。

public enum  SingletonEnum {
    INSTANCE;
    public void doSomething(){
        System.out.println("do sth.");
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章