單例模式(Singleton Pattern)
單例:即單個實例,實例需要new,所以是 創建型
單例模式特點:
1、單例類只能有一個實例。
2、單例類必須自己創建自己的唯一實例。
3、單例類必須給所有其他對象提供這一實例。
懶漢式和餓漢式主要是加載時間存在差別,即是否是在構造函數中new,這其實是類加載的相關知識,這裏不再贅述。
通過 內部嵌套類 的方式編寫單例模式
代碼如下:
public class Singleton {
private Singleton() {
System.out.println("Sigleton的無參構造函數初始化了");
}
public static Singleton getInstance() {
return InnerClass.instance;
}
// 內部嵌套類,注意是private,只能夠在Singleton中使用
private static class InnerClass {
private static Singleton instance = null;
// static會被提前執行,具體知識可以從網上查找 加載順序相關的內容
static {
System.out.println("InnerClass 靜態代碼初始化了");
instance = new Singleton();
}
}
}
測試代碼:
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
// 用==來比較是否爲同一個對象
System.out.println(instance == instance1);
}
加載順序(這裏只提及方法,不提及常量的加載):
InnerClass的static{}
給自己的instance
賦值Singleton
的無參構造函數Singleton()
Singleton.getInstance()
調用Singleton
的getInstance()
InnerClass
中的instance
已經賦過值了,直接return InnerClass.instance;
返回- 再次執行
Singleton instance1 = Singleton.getInstance();
時直接return InnerClass.instance;
返回
測試結果:
InnerClass 靜態代碼初始化了
Sigleton的無參構造函數初始化了
true // instance == instance1
補充內容:
雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking)
這種方式採用雙鎖機制,安全且在多線程情況下能保持高性能。
代碼如下:
public class Singleton {
private volatile static Singleton instance = null;
private Singleton() {
System.out.println("Sigleton的無參構造函數初始化了");
}
public static Singleton getInstance() {
// 如果沒有這個判斷,線程會排隊等synchronized的鎖
// 等拿到鎖,判斷髮現instance不爲null 就白等了
// 而且沒拿過鎖的線程還不知道,繼續傻等,白白浪費性能
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
具體測試與上面相同,當然可以開多線程進行測試這裏不再贅述。
最後的補充:
枚舉也是一種單例模式!!!
代碼已經上傳到Git:請點擊訪問
如果大家對於單例模式還有更多的使用技巧和使用心得,歡迎評論並在評論中分享自己的鏈接!