Java 單例模式與線程安全

1.惡漢式

public class Singleton {

    private static Singleton INSTANCE = new Singleton();

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

優點:類加載的時候就完成了創建對象,不用考慮線程同步問題

缺點:沒有實現懶加載的效果,如果創建了該對象而不使用,造成內存資源浪費

2.懶漢式

public class Singleton {

    private static Singleton INSTANCE;

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

優點:實現了懶加載的方式

缺點:多線程獲取單例對象時,由於對象還未創建,會導致創建多個實例,多線程非安全

3.懶漢式(線程同步)

public class Singleton {

    private static Singleton INSTANCE;

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

public class Singleton {

    private static Singleton INSTANCE;

    public static Singleton getInstance() {
        if (INSTANCE == null) {

            synchronized (Singleton.class) {
                return new Singleton();
            }
        }
        return INSTANCE;
    }
}

缺點:第一種,每次都是訪問鎖,會造成資源浪費

           第二種,多線程訪問時,null的條件同時成立,在訪問鎖時,由於鎖的監視器是類,JVM只存在一個class對象,雖然會進行線程同步,但是一個線程在創建對象並且進行對象地址賦值時,由於機器可能會進行指令性重排,導致還instance未賦值就運行另個一個線程的getInstance方法,返回的實例並未初始化

4.雙重檢查+防止指令性重排

public class Singleton {

    private volatile static Singleton INSTANCE;

    public static Singleton getInstance() {
        if (INSTANCE == null) {

            synchronized (Singleton.class) {
                return new Singleton();
            }
        }
        return INSTANCE;
    }
}

優點:延遲加載,線程同步

5.靜態內部類

public class Singleton {
    
    private static class SingletonInnerClass {
        private static final Singleton instance = new Singleton();
    }

    public Singleton getInstance() {
        return SingletonInnerClass.instance;
    }
}

優點:實現了延遲加載,而且不用考慮線程同步,Singleton 類在被裝載時,靜態內部類並不會立即初始化,只有在調用創建實例方法時靜態內部類 纔會被裝載,實現了對象的初始化

 

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