單列模式

一:單列模式的定義

確保某個類只有一個實例。

二:線程安全

說起單列模式,不得不提線程安全,那么什么是線程安全?我們通過幾種方式來說說

1.多線程訪問時,采用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問直到該線程讀取完,其他線程才可使用。不會出現數據不一致或者數據污染。就是線程安全的。

2.你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。

3.一個類或者程序所提供的接口對于線程來說是原子操作,或者多個線程之間的切換不會導致該接口的執行結果存在二義性,也就是說我們不用考慮同步的問題,就是線程安全的。

三:單列模式的幾種寫法
1:惡漢單列

優點:寫法比較簡單,在類裝載的時候就完成實例化。避免了線程同步問題,天生線程安全。

缺點:類裝載的時候就完成實例化,一定程度上會造成資源的浪費。

public class Singleton {

    private static final Singleton INSTANCE=new Singleton();

    private Singleton(){
    }

    public static Singleton getInstance(){
        return INSTANCE;
    }
}
2:懶漢單列

優點:只有使用時,才被實例化。

缺點:效率低,第一次加載需要實例化,反應稍慢。每次調用getInstance方法都會進行同步,消耗不必要的資源。

public class Singleton {

    private static Singleton instance;

    private Singleton(){

    }

    public static synchronized Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}
3:雙重檢查單列

優點:資源利用率高,效率高。

缺點:第一次加載時反應稍慢。某些情況下失效。

public class Singleton {

    private static Singleton instance;

    private Singleton(){

    }

    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
4:靜態內部類單列(推薦使用)

優點:保證了線程安全,資源利用率高,效率高。

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}
5:枚舉單列(推薦使用)

優點:寫法簡單,任何情況下都是一個單列。前面幾種方法會在反序列化的時候,重新創建對象。
缺點:實例化一個單例類的時候,必須要記住使用相應的獲取對象的方法。并且枚舉在SDK1.5中才添加。

public enum SingletonEnum {

    INSTANCE;
    public void doSomething() {

    }
}
五:其他方式

除了以上方式,還可以使用容器形式實現單列

public class SingletonManager {

    private static Map<String, Object> objMap = new HashMap<>();

    private SingletonManager() {

    }

    public static void putObject(String key, String instance){
        if(!objMap.containsKey(key)){
            objMap.put(key, instance);
        }
    }

    public static Object getObject(String key){
        return objMap.get(key);
    }
}
四:備注

不管哪種方式實現,核心原理都是講構造函數私有化,通過靜態方法獲取一個唯一的實例,且保證線程安全、防止反序列化導致重新生成實例對象等問題。
實現方式取決項目本身。

另外,附上防止反序列化時重新生成對象方法:

private Object readResolve() throws ObjectStreamException {
    return instance;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容