☺ 對於單例模式,個人學習需要掌握
- 注意答案的重點標黑了。對於單例模式,掌握,我下面這幾點就很棒棒。
1、知道什麼是單例:
答:一個類有且僅有一個例項,[
單例
],單例模式保證了系統記憶體中該類只存在一個物件,節省了系統資源,對於一些需要頻繁建立銷燬的物件,使用單例模式可以提高系統效能。例項化物件的時候,是通過相應的方法,而不是直接new2、單例模式的意義:節省系統資源
答:[一個類僅僅有一個唯一的物件,並且提供一個全域性的訪問點],節省系統資源。具體場景:例如公共的全域性配置。
公共的全域性配置在系統執行時候,就需要載入一些配置和屬性,這些配置和屬性是一定存在了,又是公共的,同時需要在整個生命週期中都存在,所以只需要一份就行,使用單例模式實現。
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工廠等)
如果本文對你有幫助的話記得給一樂點個贊哦,感謝!