設計模式之單例模式 Singleton實現
阿新 • • 發佈:2017-09-02
-- throw return null mage demo1 nbsp 定義 所在
餓漢式
- 餓漢式單例模式,static變量會在類裝載時初始化,此時也不會涉及多個線程對象訪問該對象的問題。虛擬機保證只會裝載一次該類,肯定不會發生並發訪問的問題,
因此可以省略synchronized關鍵字
- 問題:如果只是加載本類,而不是要調用getInstance(),甚至永遠沒有調用,則會造成資源浪費
public class SingletonDemo1 { //類初始化時,立即加載這個對象(沒有延時加載的優勢),,記載類時,天然的是線程安全的 private staticSingletonDemo1 instance = new SingletonDemo1(); private SingletonDemo1(){ }; //方法沒有同步,效率高 public static SingletonDemo1 getInstance(){ return instance; } }
懶漢式
- Lazy Load,延時加載,真正用到的時候再加載
- 每次都得使用同步,synchronized,效率就底下了。
public class SingletonDemo2 {//類初始化時,不初始化這個對象,(延時加載,真正用到的時候再創建) private static SingletonDemo2 instance ; private SingletonDemo2(){ }; //方法同步,效率低 public static synchronized SingletonDemo2 getInstance(){ if(instance==null){ instance= new SingletonDemo2(); }return instance; } }
雙重檢測鎖
- 雙重檢測判斷
- 使用volatile關鍵字,保證可見性
public class Singleton { private volatile static Singleton sSingleton; private Singleton() { } public static Singleton getSingleton() { if (sSingleton == null) { synchronized (Singleton.class) { if (sSingleton == null) { sSingleton = new Singleton(); } } } return sSingleton; } }
靜態內部類
- 外部類沒有static關鍵字,所以不會立即加載
- 只有調用getInstance()時才會加載靜態內部類,線程安全。instance前面加了static final關鍵字,因此保證了內存中只有這樣一個實例存在,且只能賦值一次,final保證線程安全
- 具有並發高效調用和延遲加載的雙重優點
public class SingletonDemo3 { private static class SingletonClassInstance{ private static final SingletonDemo3 instance = new SingletonDemo3() ; } private SingletonDemo3(){ } public static SingletonDemo3 getInstance(){ return SingletonClassInstance.instance; } }
枚舉實現
- 實現簡單
- 枚舉本身就是單例模式
public enum SingletonDemo4 { //枚舉元素本身就是單例對象 INSTANCE; //添加自己需要的操作 public void singletonOperation(){ } }
如何防止反射和反序列化漏洞
- 反射可以破解上面幾種(不包含枚舉式)實現方式 --------------------------可以在構造方法中手動拋出異常控制
- 反序列化可以破解上面幾種(不包含枚舉式)實現方式
-------可以通過定義readResolve()防止獲得不同對象。
--------反序列化時,如果對象所在類定義了readResolve(),定義返回哪個對象,實際是一種回調。
public class SingletonDemo5 { //類初始化時,不初始化這個對象,(延時加載,真正用到的時候再創建) private static SingletonDemo5 instance ; private SingletonDemo5(){ if(instance !=null){ throw new RuntimeException(); } } //方法同步,效率低 public static synchronized SingletonDemo5 getInstance(){ if(instance==null){ instance= new SingletonDemo5(); } return instance; } //反序列化時,如果定義了readResolve(),則直接返回此方法指定的對象,而不需要單獨創建新的對象 private Object readResolve(){ return instance; } }
五種單例模式比較
單例對象占用資源少,不需要延時加載 -------枚舉類好於餓漢式
單例對象占用資源大,需要延時加載 -------靜態內部類好於懶漢式
設計模式之單例模式 Singleton實現