單例模式的幾種寫法及分析

一、有什么用

保證應用程序中只有該類的一個實例

二、特點

好的單例模式應保證:1)線程安全;2)延遲加載:真正使用的時候才去創(chuàng)建實例,不用的時候不創(chuàng)建;3)類的構造函數(shù)一般用 private 修飾,不對外公開。

三、可用的幾種單例實現(xiàn)

1.餓漢

/**
 * 
 * <p>
 * Description: 餓漢模式
 * 優(yōu)點:線程安全
 * 缺點:無延時加載(過早的創(chuàng)建實例,降低內存使用率)
 * </p>
 * 
 * @author 楊麗金
 * @date 2018-4-8
 * @version 1.0
 */
public class Singleton4 {
    private Singleton4() {}
    
    /**
     * 類的初始化階段即為執(zhí)行<clinit>方法的階段。
     * 聲明靜態(tài)變量時的初始化操作+static初始化塊中語句=>被合并到<clinit>方法中。
     * JVM保證執(zhí)行<clinit>方法時:該方法可被正確的加鎖、同步,保證了Singleton4對象創(chuàng)建時的線程安全
     * 故:JVM可保證只創(chuàng)建該類的一個實例
     */
    private static Singleton4 instance=new Singleton4();

    /**
     * 當類的靜態(tài)方法被調用時,初始化類(當然之前要完成加載、驗證、準備)
     * @return
     */
    public static Singleton4 getInstance() {
        return instance;
    }
    
}

2. 懶漢模式

public class Singleton {
    private Singleton(){}
    
    private static Singleton instance;

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

該方法可保證實例的唯一性,不足之處是:第一次初始化后,再獲取實例還要進行同步操作,造成不必須的系統(tǒng)開銷。

3.雙重檢查鎖定單例模式

優(yōu)點:線程安全;延遲加載
缺點:代碼復雜,容易出錯
特點:1,volatile修飾;2,雙重檢查

/**
 * 
 * <p>
 * Description: 懶漢模式
 * 缺點:代碼復雜,容易出錯
 * </p>
 * 
 * @author 楊麗金
 * @date 2018-4-8
 * @version 1.0
 */
public class Singleton3 {
    private Singleton3() {
    }

    /**
     * 這里要用volatile:防止new Singleton3()操作的指令重排序導致的錯誤
     * (JDK1.5以后這種錯誤才因volatile的出現(xiàn)得以避免;JDK1.5之前,毛的辦法)
     */
    private volatile static Singleton3 instance = null;

    public static Singleton3 getInstance() {
        // 這樣的好處是:在實例還未創(chuàng)建時需要加鎖,創(chuàng)建以后則不需加鎖了
        if(instance==null){
            synchronized(Singleton3.class){
                if (instance == null) {
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
    
}

注意instance = new Singleton();這行代碼,它的執(zhí)行可以分解為第三個步驟:(1)為instance實例分配內存。(2)執(zhí)行Singleton構造函數(shù)來初始化instance。(3)將instance指向分配的內存。
但在JDK1.5前,上邊的(2)(3)無法保證按順序執(zhí)行,如果按(1)(3)(2)順序,假如A線程執(zhí)行完(3),(2)未執(zhí)行就被切換到B線程,因為步驟(3)已經(jīng)在A線程執(zhí)行,則B線程直接取走了認為非空instance,這就導致雙重檢查鎖定的判斷失效。

4.靜態(tài)內部類單例模式

優(yōu)點:線程安全;延遲加載
缺點:無
特點:由于在讀取實例的時候不會進行同步,所以沒有性能缺陷;沒有使用 volatile ,也不依賴 JDK 版本

/**
 * 
 * <p>
 * Description: 靜態(tài)內部類單例模式
 * 優(yōu)點:線程安全,懶加載
 * 缺點:無明顯缺點
 * </p>
 * 
 * @author 楊麗金
 * @date 2018-4-8
 * @version 1.0
 */
public class Singleton5 {
    private Singleton5() {
    }

    /**
     * 當類的靜態(tài)方法被調用時,初始化類(當然之前要完成加載、驗證、準備)
     * @return
     */
    public static Singleton5 getInstance() {
        /**
         * 當獲取SingletonHolder的靜態(tài)變量的值時,SingletonHolder類被初始化,
         * 其中創(chuàng)建Singleton對象的操作在SingletonHolder的<clinit>方法中,
         * 由JVM加鎖同步,保證線程安全
         */
        return SingletonHolder.instance;
    }
    
    /**
     * 當類Singleton5被初始化時不會加載初始化SingletonHolder,這樣達到了懶加載的效果
     */
    private static class SingletonHolder{
        /*這里的私有沒有什么意義
        private*/ static Singleton5 instance=new Singleton5();
    }
    
}

參考文獻

小小芳_單例模式
【單例深思】靜態(tài)內部類實現(xiàn)詳解
【單例深思】餓漢式與類加載
設計模式
SheHuan_單例模式

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 單例模式(SingletonPattern)一般被認為是最簡單、最易理解的設計模式,也因為它的簡潔易懂,是項目中最...
    成熱了閱讀 4,533評論 4 34
  • 【學習難度:★☆☆☆☆,使用頻率:★★★★☆】直接出處:單例模式梳理和學習:https://github.com/...
    BruceOuyang閱讀 737評論 1 2
  • 概念 確保某一個類只有一個實例,而且自行實例化,并向整個系統(tǒng)提供一個訪問它的全局訪問點,這個類稱為單例類。 特性 ...
    野狗子嗷嗷嗷閱讀 613評論 0 2
  • 1.單例模式概述 (1)引言 單例模式是應用最廣的模式之一,也是23種設計模式中最基本的一個。本文旨在總結通過Ja...
    曹豐斌閱讀 3,062評論 6 47
  • 總會遇到各種“牛人“,聽他們講天南海北各種牛逼哄哄的故事。 每每這個時候,是否就只有自己成為了最low的那個。 我...
    善余心閱讀 217評論 0 0

友情鏈接更多精彩內容