單例模式:顧名思義就是物件的實體只有一個
實作單例模式的方式有多種方式
1、餓漢式
// 餓漢式單例
public class Singleton1 {
// 私有構造
private Singleton1() {}
private static Singleton1 single = new Singleton1();
// 靜態工廠方法
public static Singleton1 getInstance() {
return single;
}
}
餓漢式是在類加載初始化的時候就已經吧物件創建好了,提供了一個靜態的工廠方法供使用者呼叫,除非系統重啟不然物件不會消失,本身也是執行緒安全的,但是有一個缺點就是不管后面用不用這個物件都會被創建,
2、.懶漢式
// 懶漢式單例
public class Singleton2 {
// 私有構造
private Singleton2() {}
private static Singleton2 single = null;
public static Singleton2 getInstance() {
if(single == null){
single = new Singleton2();
}
return single;
}
}
實作了使用時才能創建單例物件,但是存在現在安全問題,多執行緒時會實體化多個物件,不能保證單例,一般都會用synchronizeds與valatile來保證其執行緒安全
public class Singleton3 {
// 私有構造
private Singleton3() {}
private volatile static Singleton3 single = null;
// 雙重檢查
public static Singleton3 getInstance() {
if (single == null) {
synchronized (Singleton3.class) {
if (single == null) {
single = new Singleton3();
}
}
}
return single;
}
}
關于valatile的作用有禁止指令重排序、記憶體可見性,百度一下二者作用再結合下面的話就能知道
多個執行緒同時對single訪問時雖然有synchronized關鍵字但是當第一個執行緒創建物件后,jvm會給資料分配記憶體,在此程序中可能第二個執行緒已經進來,此時對于第二個執行緒來說single依舊是null,依舊會再去創建,valatile關鍵字會保證多執行緒場景下一個執行緒對資料改變,其他執行緒立刻可見,所以要加valatile關鍵字
除了上面二種常用的,下面也有幾種可以實作
3、靜態內部類
public class Singleton3 {
// 私有構造
private Singleton3() {}
// 靜態內部類
private static class InnerObject{
private static Singleton3 single = new Singleton3();
}
public static Singleton3 getInstance() {
return InnerObject.single;
}
}
4、靜態代碼塊
public class Singleton4 {
// 私有構造
private Singleton4() {}
private static Singleton4 single = null;
// 靜態代碼塊
static{
single = new Singleton4();
}
public static Singleton4 getInstance() {
return single;
}
}
另外在spring中也有不少地方用到單例模式,spring的依賴注入,AOP的切點定義中等,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/242340.html
標籤:其他
