1、普通單例模式
此類缺陷:無法應對多線程問題
package com.boonya.pattern.singleton;/** * 單例樣本 * <li>檔案名稱: Singleton</li> * <li>檔案描述: $單例樣本類</li> * <li>內容摘要: 單例的建立</li> * <li>完成日期:2013-9-27</li> * <li>樣本編寫: BOONYACHENGDU@GMAIL.COM</li> * <li>應用情境:頻繁使用的對象且值不變,一如組件之類的對象</li> */public class Singleton{/** * 無論是否調用都會執行個體化 */ private static Singleton singleton=new Singleton();/** * 確保外部不能執行個體化,即使用new關鍵字無效 */private Singleton(){System.out.println("singleton constructor");}/** * 必須確保同步,否則多線程情況下值不統一 但 synchronized 關鍵字使用會降低系統效能 */public static /*synchronized*/ Singleton getInstance(){return singleton;}}
2、懶載入單例模式
此類缺陷:使用多線程時系統效能明顯下降
package com.boonya.pattern.singleton;/** * 單例樣本 * <li>檔案名稱: LazySingleton</li> * <li>檔案描述: $單例樣本類</li> * <li>內容摘要: 單例的建立</li> * <li>完成日期:2013-9-27</li> * <li>樣本編寫: BOONYACHENGDU@GMAIL.COM</li> * <li>應用情境:頻繁使用的對象且值不變,一如組件之類的對象</li> */public class LazySingleton{/** * 調用的時候再執行個體化 */private static LazySingleton singleton=null;/** * 確保外部不能執行個體化,即使用new關鍵字無效 */private LazySingleton(){System.out.println("singleton constructor");}/** * 必須確保同步,否則多線程情況下值不統一(線程執行先後可能判斷為null) */public static synchronized LazySingleton getInstance(){if(singleton==null){singleton=new LazySingleton();}return singleton;}}
3、加強(plus)單例
此類缺陷:使用反射機制時,會強行調用單例類的私人構造器,產生多個執行個體
package com.boonya.pattern.singleton;/** * 單例樣本 * <li>檔案名稱: PlusSingleton</li> * <li>檔案描述: $單例樣本類</li> * <li>內容摘要: 單例的建立</li> * <li>完成日期:2013-9-27</li> * <li>樣本編寫: BOONYACHENGDU@GMAIL.COM</li> * <li>應用情境:頻繁使用的對象且值不變,一如組件之類的對象</li> */public class PlusSingleton{/** * 確保外部不能執行個體化,即使用new關鍵字無效 */private PlusSingleton(){System.out.println("singleton constructor"); }/** * 內部類JVM初始換調用 */private static class SingletonObject{private static PlusSingleton singleton=new PlusSingleton();}/** * 不需要考慮多線程問題 */public static PlusSingleton getInstance(){return SingletonObject.singleton;}}
4、序列化單例
此類缺陷:序列化和還原序列化都有可能會破壞單例
package com.boonya.pattern.singleton;import java.io.Serializable;/** * 單例樣本 * <li>檔案名稱: Singleton</li> * <li>檔案描述: $單例樣本類</li> * <li>內容摘要: 單例的建立</li> * <li>完成日期:2013-9-27</li> * <li>樣本編寫: BOONYACHENGDU@GMAIL.COM</li> * <li>應用情境:頻繁使用的對象且值不變,一如組件之類的對象 序列化操作需謹慎</li> */@SuppressWarnings("serial")public class SerializableSingleton implements Serializable{private String context;public String getContext(){return context;}public void setContext(String context){this.context = context;}/** * 無論是否調用都會執行個體化 */ private static SerializableSingleton instance=new SerializableSingleton();/** * 確保外部不能執行個體化,即使用new關鍵字無效 */private SerializableSingleton(){System.out.println("singleton constructor");context="SerializableSingleton";}/** * 擷取單例對象 */public static SerializableSingleton getInstance(){return instance;}/** * 阻止產生新的執行個體,總是返回當前對象(此方法不可去掉否則序列化和還原序列化會出錯) */private Object readResolve(){return instance;}}
5、效能和注意事項
(1)、頻繁使用的對象且值不變,一如組件之類的對象建議使用單例。此處建議使用懶載入方式,使用的時候再執行個體化,降低JVM初始化static 時new執行個體化對象消耗效能,減少GC機制的執行。
(2)、考慮是否會在多線程中使用到,多線程中使用單例消耗效能嚴重。
(3)、使用單例時,盡量不要使用序列化操作,危險難以預測,最好是具體問題具體分析。