性價比超高的設計模式——單例模式

爲何說單例模式性價比高?
在面試過程當中常常讓手擼的一種設計模式,而且被面的頻率很是高。重點是這種設計模式很簡單!java

個人我的博客(後臺建站,Tomcat集羣,Redis分佈式,nginx,適合初學者)nginx

爲何要用單例模式?面試

在開發過程當中,根據需求的不一樣,有時可能要求對象實例只能有一個,這時就要使用到了單例模式。設計模式

如:Spring中的bean默認使用的都是單例模式。安全

什麼是單例模式?cookie

確保對象只有一個,並提供一個全局訪問點。分佈式

1、單例模式初探

經典的實現方式:性能

餓漢式線程

public  class Singleton1{
    private static Singleton1 uniqueInstance = new Singleton1();
    private Singleton1() {
        super();
    }
    
    public static Singleton1 getInstance(){
        return uniqueInstance;
    }
}

懶漢式設計

public  class Singleton2{
    private static Singleton2 uniqueInstance = null;
    private Singleton2(){
        super();
    }
    
    public static Singleton2 getSinleton(){
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton2();
        }
        return uniqueInstance;
    }
}

進階實現方式

雙重檢查加鎖

public class Singleton3{
    private  static volatile Singleton3 uniqueInstance = null;
    private Singleton3 (){
        super();
    }
    
    public static Singleton3 getInstance() {
        if (uniqueInstance == null){
            synchronized (Singleton3.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton3();
                }
            }
        }
        return uniqueInstance;
    }
}

靜態內部類

public class Singleton4{
    
    private Singleton4() {
        super();
    }
    private static  class Holder{
        private static final Singleton4 uniqueInstance = new Singleton4();
    }
    
    public static final Singleton4 getInstance(){
        return Holder.uniqueInstance;
    }
}

2、分析與比較

餓漢式: 在類加載時就建立對象,不管是否使用都會建立,天生線程安全。

懶漢式:延遲化實例,在使用時纔會建立,線程不安全,相比餓漢式來講對於資源敏感的對象很重要,能節省系統資源。

雙重校驗:延遲化實例,線程安全,可是犧牲性能來提高安全。

靜態內部類:只有在,內部類在第一次調用Holder.uniqueInstance時纔會建立實例,因此也是一種延遲化實例的機制,經過靜態內部類只有第一次引用纔會被加載,因此是線程安全的;而且經過反射,也沒法從外部類獲取內部類的屬性。因此這種形式,很好的避免了反射入侵。

3、總結

爲何進行雙重校驗?

因爲同步範圍比較精確,也可能出現安全問題,即在判斷爲null和加鎖之間另外一個線程已經建立了對象,由於使用了volitile關鍵字保證了對象的可見性,因此必須在此進行二次檢查,不然式去了同步的意義。

如何選擇適當的方案?

①系統是不是資源敏感型?

若是對系統資源不敏感,懶漢式式一種不錯的選擇!

②是否有性能上考慮?

若是沒有性能上考慮,可使用懶漢式!

若是有性能考慮,應使用雙重檢查加鎖或靜態內部類!

注:靜態內部類也有一些缺點,須要兩個類才能實現,雖然不會建立靜態內部類的對象,可是其 Class 對象仍是會被建立,並且是屬於永久代的對象。

個人我的博客(後臺建站,Tomcat集羣,Redis分佈式,nginx,適合初學者)

相關文章
相關標籤/搜索