Java單例模式(懶漢 餓漢 雙檢鎖)


單例模式:一種創建型設計模式 讓你能夠保證一個類只有一個實例 並提供一個訪問該實例的全局節點

方法為私有化構造函數,在類中定義靜態實例(先new為餓漢 后new為懶漢)

在方法定義靜態方法,返回唯一實例

下面介紹三種單例模式java代碼寫法

1。懶漢式(需要用時再申請)缺點:有線程不安全風險  

(2021/1/18更新:為什么不安全呢?

競態條件的類型“先檢查后執行”的一種情況——延遲初始化

假設有線程A B同時執行這個方法,A看到是null的,取決於時序、線程調度方式,如果B同樣需要看到是null的(未初始化完成),則會出現覆蓋)

class lhan {
    private int address = 1999;
    private static lhan instance;
    //私有化構造函數 外部只能用實例調用 無法新聲明新實例
    private lhan() {
    }
     void put(int k) {
        address = k;
        return;
    }
     int get() {
        return address;
    }
    //返回唯一實例
    public static lhan getInstance() {
        if (instance == null) {
            instance = new lhan();
        }
        return instance;
    }
}

2.餓漢式(不管是否調用 先申請)  優點:線程安全。   缺點:如果不調用的話浪費內存

class ehan{
    private int age=20;
    private ehan(){};//私有化構造函數
    private static ehan instance=new ehan();
    void put(int k) {
        age = k;
        return;
    }
    public int get() {
        return age;
    }
    public static ehan getInstance()
    {
        return instance;
    }
}

3.雙檢鎖式(綜合了餓漢 懶漢的優點 並改正了其缺點)

這樣既保證了線程安全,又比直接上鎖提高了執行效率,還節省了內存空間。

 

class DoubleCheack{
    private static DoubleCheack instance;
    private int age=1;
    private DoubleCheack(){};
    void put(int k) {
        age = k;
        return;
    }
    public int get() {
        return age;
    }
    public static DoubleCheack getInstance()
    {
        if(instance==null) {//先判斷是否為null 后上鎖進行初始化
            synchronized (DoubleCheack.class) {
                if (instance == null)//將對象上鎖之后再次判斷 是否有別的線程初始化了
                    instance = new DoubleCheack();
            }
        }
        return instance;
    }
}

主函數測試用例(雙檢鎖)

 

 無論對於幾個實例內數據如何變動 都指向一個唯一實例(instance)

 

 

參考博文:

https://blog.csdn.net/absolute_chen/article/details/93380566


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM