09_單例模式

Duckdan發表於2020-11-21

一、懶漢式

1.1 雙重檢查機制

09_單例模式
package com.study.single_instance.java.lazy;

public class DoubleCheckSingleInstance {
    /**
     * 禁止重排序:volatile關鍵字保證所有執行緒都能看到共享記憶體的狀態,保證了記憶體的可見性。
     * 用volatile修飾的共享變數在進行寫操作的時候,當前處理器快取行的資料寫回到系統記憶體,
     * 同時使得其它CPU快取了該記憶體地址的資料無效。
     * 當處理器發現快取無效之後,就會在去系統記憶體中獲取資料。(快取一致性協議)
     */
    private volatile static DoubleCheckSingleInstance doubleCheckSingleInstance=null;
    private DoubleCheckSingleInstance(){}
    public static DoubleCheckSingleInstance getInstance(){
        if(doubleCheckSingleInstance==null){
            synchronized (DoubleCheckSingleInstance.class) {
                if(doubleCheckSingleInstance==null) {
                    /**
                     * doubleCheckSingleInstance = new DoubleCheckSingleInstance();分為三步
                     * 1.分配物件的記憶體空間
                     * 2.初始化物件
                     * 3.設定instance指向記憶體空間
                     */
                    doubleCheckSingleInstance = new DoubleCheckSingleInstance();
                }
            }
        }
        return doubleCheckSingleInstance;
    }
}

1.2 靜態內部類的方式

09_單例模式
package com.study.single_instance.java.lazy;

public class StaticClassSingleInstance {
    private static StaticClassSingleInstance staticClassSingleInstance=null;
    private StaticClassSingleInstance(){ }

    private static class InnerInstanceHolder{
        /**
         * 只有當有執行緒呼叫getInstance方法時,staticClassSingleInstance才會被初始化。
         * Class被載入之後以及被執行緒使用之前都是類的初始化階段,在這個階段
         * JVM會執行初始化,JVM會去獲取一個鎖。這個鎖可以同步多個執行緒對一個
         * 類的初始化,這時候只有持有這個鎖的執行緒才能看到類的初始化過程中的
         * 重排序。
         *
         */
        private  static StaticClassSingleInstance staticClassSingleInstance=new StaticClassSingleInstance();
    }


    public static StaticClassSingleInstance getInstance(){
        return InnerInstanceHolder.staticClassSingleInstance;
    }
}

二、餓漢式

2.1 成員變數初始化

package com.study.single_instance.java.hungry;

import java.io.Serializable;

public class LazySingleInstance implements Serializable,Cloneable {
    private final static LazySingleInstance lazySingleInstance=new LazySingleInstance();
    private LazySingleInstance(){}
    public static LazySingleInstance getInstance(){
        return lazySingleInstance;
    }

    //用於反序列化呼叫,方法簽名要與下列方法簽名一致才可以,因為在反序列化的
    //過程中虛擬機器會去檢測當前內中是否存在該方法。
    public Object readResolve(){
        return lazySingleInstance;
    }
}

2.2 成員變數靜態程式碼塊初始化

package com.study.single_instance.java.hungry;

public class LazyStaticInitSingleInstance {
    private final static LazyStaticInitSingleInstance lazyStaticSingleInstance;
    static {
        lazyStaticSingleInstance = new LazyStaticInitSingleInstance();
    }
    private LazyStaticInitSingleInstance(){}
    public static LazyStaticInitSingleInstance getInstance(){
        return lazyStaticSingleInstance;
    }

}

三、多執行緒除錯方法

09_單例模式
09_單例模式

相關文章