單例模式:保證在⼀個JVM中,該物件只有⼀個範例存在;
適⽤場景:
1、某些類建立⽐較頻繁,對於⼀些⼤型的物件,這是⼀筆很⼤的系統開銷。
2、省去了new操作符,降低了系統記憶體的使⽤頻率,減輕GC壓⼒。
3、有些類如交易所的核⼼交易引擎,控制著交易流程,如果該類可以建立多個的話,系統完全亂了。(⽐如⼀個軍隊出現了多個司 令員同時指揮,肯定會亂成⼀團),所以只有使⽤單例模式,才能保證核⼼交易伺服器獨⽴控制整個流程。
程式碼:
1 public class Singleton{ 2 //持有私有靜態範例,防止被參照,賦值為null,目的就是實現延遲載入 3 private static Singleton instance = null; 4 5 6 //私有構造方法,防止被範例化。 7 private Singleton(){ 8 } 9 10 //建立範例 11 public static Singleton getInstance() 12 { 13 if (instance=null){ 14 instance=new Singleton(); 15 16 } 17 return instance; 18 //如果該物件被⽤於序列化,可以保證物件在序列化前後保持⼀致 19 public Object readReaslove(){ 20 return instance; 21 } 22 23 } 24 }
分類:
1.餓漢式:類初始化時建立單例,執行緒安全,但佔用記憶體空間大,適⽤於佔記憶體⼩的場景,否則推薦使⽤懶漢式延遲載入;
public class Singleton{
private static Singleton instance = new Singleton();
//構造器私有, 外部就無法new這個物件,保證一個類中只有一個範例物件
private Singleton(){}
public static Singleton newInstance(){ return instance; } }
2.懶漢式:需要單例範例的時候再建立,需要考慮執行緒安全(效能不太好)
1 public class Singleton{ 2 private static Singleton instance = null;//定義一個靜態變數指向自己 3 private Singleton(){}//私有化構造方法 4 public static synchronized Singleton newInstance(){//加鎖, 5 if (instance == null){ 6 instance = new Singleton(); 7 } 8 } 9 return instance; 10 11 }
3.雙重檢驗鎖:假如兩個執行緒A、B,A執⾏了if (instance == null)語句,它會認為單例物件沒有建立,此時執行緒切到B也執⾏了同樣的語句,B也認為單例物件沒有建立,然後兩個執行緒依次執⾏同步程式碼塊,並分別建立了⼀個單例物件。
1 public class Singleton{ 2 private static volatile Singleton instance = null; 3 private Singleton(){} 4 public static Singleton getInstance(){ 5 if (instance == null) 6 { synchronized (Singleton.class){ 7 if (instance == null){ 8 instance = new Singleton(); 9 10 } 11 } 12 } 13 return instance; 14 }
4.靜態內部類:可以同時保證延遲載入和執行緒安全。靜態內部類單例是如何實現懶載入的呢?(懶載入 :使⽤的時候再建立物件)⾸先,我們先了解下類的載入時機。
1 public class Singleton{ 2 private Singleton(){}//私有化構造方法 3 public static Singleton getInstance(){//對外提供獲取範例的公共方法 4 return InnerClass.Instance;} 5 private static class InnerClass{//定義靜態內部類 6 private final static Singleton Instance=new Singleton; 7 8 } 9 10 }
5.列舉:
1 public enum Singleton{ 2 instance; 3 public void whateverMethod(){} 4 }