設計模式之---單例模式

一樂樂發表於2022-06-07

☺ 對於單例模式,個人學習需要掌握

  • 注意答案的重點標黑了。對於單例模式,掌握,我下面這幾點就很棒棒。

1、知道什麼是單例:

答:一個類有且僅有一個例項,[單例],單例模式保證了系統記憶體中該類只存在一個物件,節省了系統資源,對於一些需要頻繁建立銷燬的物件,使用單例模式可以提高系統效能。例項化物件的時候,是通過相應的方法,而不是直接new

2、單例模式的意義:節省系統資源

答:[一個類僅僅有一個唯一的物件,並且提供一個全域性的訪問點],節省系統資源。具體場景:例如公共的全域性配置。

公共的全域性配置在系統執行時候,就需要載入一些配置和屬性,這些配置和屬性是一定存在了,又是公共的,同時需要在整個生命週期中都存在,所以只需要一份就行,使用單例模式實現。

3、單例模式的使用場景

答:需要頻繁的進行建立和銷燬的物件、經常用到的重量級物件(建立物件時耗時很多或耗費資源很多)、工具類物件、頻繁訪問資料庫或檔案的物件(比如資料來源、session工廠等)

4、單例模式的方式

  • 個人需要掌握:很簡單的餓漢式(靜態常量/靜態程式碼塊)、懶漢式(雙重檢查)、靜態內部類
  • 瞭解開發中推薦使用的模式餓漢式(靜態常量/靜態程式碼塊)、雙重檢查 (懶漢式的改良實用版)、 靜態內部類列舉方式
  • 在掌握雙重檢查的時候,可以先了解一下不推薦在開發使用的懶漢式的三種情況(執行緒不安全、執行緒安全[同步方法]、執行緒安全[同步程式碼塊])
  • 面試寫單例模式[餓漢、懶漢]的話,就寫寫餓漢式(靜態常量/靜態程式碼塊)懶漢式(雙重檢查[懶漢式的改良實用版])

5、單例模式利用了jvm的特點[在靜態內部類的模式中]

■ 靜態內部類優缺點:(利用了jvm的兩個特點,起到了懶載入、執行緒安全的作用)

  • 懶載入:利用了jvm裝載的特點:當外部類載入的時候,內部靜態類不會被載入,從而保證了懶載入。
  • 執行緒安全:當類在進行初始化的時候,別的執行緒是無法進入的。通過類的靜態屬性只會在第一次載入類的時候初始化,保證了執行緒安全



一、什麼是單例模式:

在java中的定義是:一個類有且僅有一個例項,[單例],並且自行例項化向整個系統提供。

(1) 單例模式保證了系統記憶體中該類只存在一個物件,節省了系統資源,對於一些需要頻繁建立銷燬的物件,使用單例模式可以提高系統效能

(2) 當想例項化一個單例類的時候,必須要記住使用相應的獲取物件的方法,而不是使用new

二、實現單例的步驟:

1、構造器私有化防止new,導致多個例項,而是在類內部建立物件

2、向外暴露一個靜態的公共方法 getInstance



三、單例的方式

■ 單例模式有八種方式:

餓漢式(靜態常量/靜態程式碼塊)

懶漢式(執行緒不安全/執行緒安全,同步方法/執行緒安全,同步程式碼塊)

雙重檢查

靜態內部類

列舉


★ 餓漢式和懶漢式區別:

餓漢式:在類內部一開始初始化時就建立好例項,而懶漢式是需要用的時候才去建立例項



■ 餓漢式(靜態常量/靜態程式碼塊)

在開發中推薦使用,尤其是該類的例項會用到,避免了造成記憶體的浪費,如果該類的例項不用,則會造成記憶體的浪費。

/**
* 餓漢式(靜態常量)
*/
public class Singleton{
    private static final Singleton singleton  = new Singleton();//餓漢式,初始化時就建立好了例項[使用了final常量-->餓漢式(靜態常量)]
    
    private Singleton(){}//構造器私有化,防止new,導致多個例項
    
    public static Singleton getInstance(){//向外暴露一個靜態的公共方法  getInstance
        return singleton;
    }
}
/**
* 餓漢式(靜態程式碼塊)
*/
public class Singleton{
    private static Singleton singleton  = new Singleton();//餓漢式,初始化時就建立好了例項
    
    //程式碼塊[使用了static程式碼塊-->餓漢式(靜態程式碼塊)]
    static{
        singleton = new Singleton();
    }
    
    private Singleton(){}//構造器私有化,防止new,導致多個例項
    
    public static Singleton getInstance(){//向外暴露一個靜態的公共方法  getInstance
        return singleton;
    }
}

■ 餓漢式(靜態常量) 和 餓漢式(靜態程式碼塊) 的優點、缺點:相同

□ 優點:實現較為簡單,在類載入時就完成了例項化,避免了多執行緒同步問題

□ 缺點:在類載入時就完成了例項化(使類載入的情況有很多種,不一定是呼叫getInstance()方法使類進行載入的),沒有達到懶載入的效果。如果程式從始至終未用到該例項,則造成了空間浪費


■ 懶漢式(執行緒不安全/ 執行緒安全,同步方法 / 執行緒安全,同步程式碼塊)

□ 懶漢式(執行緒不安全)

public class Singleton{
    private Singleton(){}//構造器私有化,防止new,導致多個例項
    private static Singleton singleton;
    public static Singleton getInstance(){//向外暴露一個靜態的公共方法  getInstance
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
    
}

■ 懶漢式(執行緒不安全) 優缺點:起到懶載入的效果,但是只適合在單執行緒下使用開發中不推薦使用

□ 執行緒不安全原因:如果在多執行緒下,一個執行緒進入了if (singleton == null)判斷語句塊,還未來得及往下執行,另一個執行緒也通過了這個判斷語句,這時便會產生多個例項。所以在多執行緒環境下不可使用這種方式


□ 懶漢式(執行緒安全,同步方法)

public class Singleton{
    private Singleton(){}//構造器私有化,防止new,導致多個例項
    private static Singleton singleton;
    //同步方法,synchronized直接加在方法上
    public static synchronized Singleton getInstance(){//向外暴露一個靜態的公共方法  getInstance
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }

}

■ 懶漢式(執行緒安全,同步方法) 優缺點:起到懶載入的效果,執行緒安全,但是呼叫效率低開發中不推薦使用


□ 懶漢式(執行緒安全,同步程式碼塊)

public class Singleton{
    private Singleton(){}//構造器私有化,防止new,導致多個例項
    private static Singleton singleton;
    public static Singleton getInstance(){//向外暴露一個靜態的公共方法  getInstance
        if(singleton == null){
            //同步程式碼塊,synchronized是單獨作為程式碼塊使用
            synchronized (Singleton.class){
                singleton = new Singleton();
            }     
        }
        return singleton;
    }
}

■ 懶漢式(執行緒安全,同步程式碼塊) 優缺點:起到懶載入的效果,但是只適合在單執行緒下使用開發中不推薦使用

□ 執行緒不安全原因:和 □ 懶漢式(執行緒不安全)一樣。


■ 雙重檢查

public class Singleton{
    private Singleton(){}//構造器私有化,防止new,導致多個例項
    private static volatile Singleton singleton;
    public static Singleton getInstance(){//向外暴露一個靜態的公共方法  getInstance
        //第一層檢查
        if(singleton == null){
            //同步程式碼塊
            synchronized (Singleton.class){
                 //第二層檢查
                if(singleton == null) {
                    singleton = new Singleton();
                }
            }

        }
        return singleton;
    }

}

雙重檢查優缺點:解決了同步程式碼塊方式的執行緒安全問題。

其實就是上面的 □ 懶漢式(執行緒安全,同步程式碼塊)的優化改良版。

■ 靜態內部類

public class Singleton{
    private Singleton(){}//構造器私有化,防止new,導致多個例項
    //靜態內部類,在其內部以靜態常量的方式例項化物件
    private static class SingletonInstance{
        private static final Singleton singleton = new Singleton();//常量靜態屬性,例項化物件[初始化]
    }
    public static Singleton getInstance(){//向外暴露一個靜態的公共方法  getInstance
        return SingletonInstance.singleton;
    }
}

■ 靜態內部類優缺點:(利用了jvm的兩個特點,起到了懶載入、執行緒安全的作用)

  • 懶載入:利用了jvm裝載的特點:當外部類載入的時候,內部靜態類不會被載入,從而保證了懶載入。
  • 執行緒安全:當類在進行初始化的時候,別的執行緒是無法進入的。通過類的靜態屬性只會在第一次載入類的時候初始化,保證了執行緒安全。
1.當外部類 Singleton被裝載時,靜態內部類 SingletonInstance不會被立即裝載,實現懶載入
2.當外部類 Singleton呼叫getInstance()時,靜態內部類 SingletonInstance只被裝載一次,在初始化靜態內部類SingletonInstance的靜態常量屬性 singleton,保證了執行緒安全。

■ 列舉方式

enum Singleton{
    INSTANCE;
    public void method(){
//            操作方法
    }

}

■ 列舉方式優缺點: 執行緒安全,效率高,還可防止反序列化重新建立新的物件.



四、單例的使用場景

需要頻繁的進行建立和銷燬的物件、

建立物件時耗時過多或 耗費資源過多(即:重量級物件),但又經常用到的物件、工具類物件、頻繁訪問資料庫或檔案的物件(比如資料來源、session工廠等)





如果本文對你有幫助的話記得給一樂點個贊哦,感謝!

相關文章