設計模式小抄(一) -- 單例模式

設計模式做爲開發(面試)必備(必考)知識, 咱們仍是要好好掌握. 掌握很差,那是由於你沒有準備好小抄~html

啥是小抄, 就是參考別人的答案,加上本身手抄.java

小抄參考資源:面試

《JAVA與模式》之單例模式設計模式

設計模式(二)單例模式的七種寫法安全

單例模式

先抄個 UML數據結構

單例模式的數據結構很簡單,就是一個單一的示例對象多線程

單例模式的特色

  • 單一實例
  • 由本身內部建立
  • 提供全部對象惟一訪問實例

一、餓漢式單例

很奇怪的命名方式, 咱也不知道爲啥這樣叫,咱也不敢問,先抄吧~併發

public class SimpleSingleton {
    //靜態對象,在對象初始化時,進行建立
    private static SimpleSingleton instance = new SimpleSingleton();

    private SimpleSingleton() {
    }

    //返回已經建立好的實例對象
    public static SimpleSingleton getInstance() {
        return instance;
    }
}
複製代碼

餓漢式 實際上是一種比較形象的稱謂。既然餓,那麼在建立對象實例的時候就比較着急,餓了嘛,因而在裝載類的時候就建立對象實例。(抄的)高併發

在類加載過程當中, 當咱們在初始化對象時, 會將對象中的靜態屬性初始化,所以這裏主要時利用了 類加載的相關特性,從而達到了單例的效果.spa

特色

  • 空間換時間 -- 程序啓動即存在(容易浪費內存),節省使用時建立時間(感受節省不了多少)--弊端較大
  • 線程安全 -- 利用類加載進行初始化(只會初始化一次靜態對象),線程安全

二、懶漢式單例

咱也不知道該怎麼調侃這個命名,先抄就對了~

public class LazySingleton {
    //先不初始化了, 節省點空間
    private static LazySingleton instance;

    
    private LazySingleton() { }

    //加了個鎖,排隊訪問吧 弟弟
    public static synchronized LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}
複製代碼

參考資料(答案)裏面有個非線程安全的懶漢模式,那個就是個弟弟,送命題,不抄

懶漢式 實際上是一種比較形象的稱謂。既然懶,那麼在建立對象實例的時候就不着急。會一直等到立刻要使用對象實例的時候纔會建立,懶人嘛,老是推脫不開的時候纔會真正去執行工做,所以在裝載對象的時候不建立對象實例。(也是抄的)

特色

  • 時間換空間 - 只有在使用時,纔會初始化.避免浪費空間資源
  • 低併發 - synchronized 將瘋狂請求的弟弟一個個安排在門口,響應緩慢

三、雙重檢測鎖單例(DoubleCheckLock)

也不知道這個英語有沒有拼錯,沒得抄只能蒙一下了,萬一對了呢~

public class DCLSingleton {
    //volatile 內存可見,就是能夠實時查看到更新
    private volatile static DCLSingleton instance = new DCLSingleton();

    private DCLSingleton() {
    }

    
    public static DCLSingleton getInstance() {
        if (instance == null) {
            //妹妹進來了,安排好,就那麼一次機會 好好珍惜
            synchronized (DCLSingleton.class) {
                //若是進來了個弟弟,攆出去
                if (instance == null) {
                    //初始化好
                    instance = new DCLSingleton();
                }
            }
        }
        return instance;
    }
}
複製代碼

雙重檢查加鎖機制指的是:並非每次進入getInstance方法都須要同步,而是先不一樣步,進入方法後,先檢查實例是否存在,若是不存在才進行下面的同步塊,這是第一重檢查,進入同步塊事後,再次檢查實例是否存在,若是不存在,就在同步的狀況下建立一個實例,這是第二重檢查。這樣一來,就只須要同步一次了,從而減小了屢次在同步狀況下進行判斷所浪費的時間。(仍是抄的)

這個模式,主要依賴於 volatile 關鍵字.

volatile 關鍵字的做用是: 它所修飾的變量,在發生變化時,會直接寫入內存,與其餘線程共享,從而確保在多線程下能正確獲取該變量的值

特色

  • 資源利用率高 - 解決了 懶漢模式 中對方法加鎖的尷尬狀況
  • 有缺陷 - 高併發環境下也有必定的缺陷,雖然發生的機率很小

四、 靜態內部類單例模式(Lazy initialization holder class)

此次名字英語抄對了~逼格上來了~

public class LIHCSingleton {
    private LIHCSingleton() {
    }

    //內部類,類加載過程當中,不會初始化
    private static class SingletonHolder {
        private static LIHCSingleton instance = new LIHCSingleton();
    }


    public LIHCSingleton getInstance() {
        //調用內部類時,進行初始化
        return SingletonHolder.instance;
    }
}
複製代碼

靜態內部類單例模式 - 與餓漢模式相似,經過JVM類加載機制實現了線程安全的單例模式,而且經過靜態內部類延遲加載機制,解決了 餓漢模式中出現的弊端.(本身寫的)

特色

  • 餓漢模式的優勢都有
  • 線程安全
  • 資源利用率高
  • 就很棒~

相關知識

什麼是類級內部類?

  • 簡單點說,類級內部類指的是,有static修飾的成員式內部類。若是沒有static修飾的成員式內部類被稱爲對象級內部類。

  • 類級內部類至關於其外部類的static成分,它的對象與外部類對象間不存在依賴關係,所以可直接建立。而對象級內部類的實例,是綁定在外部對象實例中的。

  • 類級內部類中,能夠定義靜態的方法。在靜態方法中只可以引用外部類中的靜態成員方法或者成員變量。

  • 類級內部類至關於其外部類的成員,只有在第一次被使用的時候才被會裝載。

五、枚舉單例

終於快抄完了,酥服

public enum EnumSingleton {
    singleton;


    public void excute(){
        //todo 作點啥都行, 你說了算
    }

}
複製代碼

默認枚舉實例的建立是線程安全的,而且在任何狀況下都是單例.(強,無敵)

《Effective Java》中有寫到: 單元素的枚舉類型已經成爲實現Singleton的最佳方法.

使用枚舉來實現單實例控制會更加簡潔,並且無償地提供了序列化機制,並由JVM從根本上提供保障,絕對防止屢次實例化,是更簡潔、高效、安全的實現單例的方式。

總結

三分靠打拼,七分天註定,剩下的90分, 大家加油哦~騷年

相關文章
相關標籤/搜索