幾種線程安全的單例

DCL(雙重檢查加鎖)

public class Singleton
{
    //volatile確保對singleton的讀寫操作不會同時進行,不會出現讀取到錯誤值的情況
    //如果不用volatile進行修飾,可能會出現在getInstance()時讀取到錯誤值的情況,因爲new不是原子操作,包含了好幾步操作,這幾步操作很可能是這樣:使singleton對象與引用相關聯發生在初始化singleton之前,這種操作在單線程下看對後面是不會有影響的,但是多線程會造成另一個線程調用getInstance()時發現singleton不是null,但其實還沒有初始化完畢導致讀到錯誤的值
    private volatile Singleton singleton = null;
    //建議所有的單例模式構造器都是私有的,防止在類外部建立多個實例
    private Singleton()  {}
    public static Singleton getInstance()   {
        //第一次檢查是否已經生成了實例
        if (singleton== null)  {
            synchronized (Singleton.class) {
                //如果有多個線程獲得了這個鎖,第二次檢查確保第二個線程進來不會再次生成新的實例
                if (singleton== null)  {
                    singleton= new Singleton();
                }
            }
        }
        return singleton;
    }
}

提前初始化模式

public class Singleton
{
    //在類被加載的時候就會生成singleton實例,所以不會有線程安全問題
    private static Singleton singleton = new Singleton();
    private Singleton()  {}
    public static Singleton getInstance()   {
        return singleton;
    }
}

延長初始化佔位類模式

public class Singleton {
    //加載Singleton類的時候不會加載SingletonHolder類,只有第一次訪問SingletonHolder類時纔會加載
    private static class SingletonHolder {
        private static Singleton INSTANCE = new Singleton();
    }
    private Singleton (){}
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

枚舉實現單例模式

public enum Singleton{
    INSTANCE;

    public void test() {
        System.out.println("你調用了test()!");
    }
}

枚舉類默認構造方法就是私有的,並且只能是私有的.

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