單例模式的五種寫法: 懶漢 惡漢 靜態內部類 枚舉 雙重校驗鎖
1.懶漢
class LazySingleton{ PRivate static LazySingleton singleton; private LazySingleton(){ } public static LazySingleton getInstance(){ if(singleton==null){ singleton=new LazySingleton(); } return singleton; } }常用的寫法。問題:沒有考慮線程安全問題,它是線程不安全的,并發環境下很可能出現多個Singleton實例
2.餓漢
class HungrySingleton{ private static HungrySingleton singleton=new HungrySingleton(); private HungrySingleton(){} public static HungrySingleton getInstance(){ return singleton; }}在類初始化時,已經自行實例化,缺點:沒有達到懶加載的效果
3.靜態內部類
class InternalSingleton{ private static class SingletonHolder{ private final static InternalSingleton INSTANCE=new InternalSingleton(); } private InternalSingleton(){} public static InternalSingleton getInstance(){ return SingletonHolder.INSTANCE; }}優點:加載時不會初始化靜態變量INSTANCE,因為沒有主動使用,達到Lazy loading。既實現了線程安全,又避免了同步帶來的性能影響
4.枚舉
public enum Singleton { INSTANCE; private String name; public String getName(){ return name; } public void setName(String name){ this.name = name; }}《Effective java》作者推薦使用的方法,優點:不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象。 雖然Effective Java中推薦使用,但是在Android平臺上卻是不被推薦的。在這篇Android Training中明確指出: Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.
5.雙重校驗鎖
class LockSingleton{ private volatile static LockSingleton singleton; private LockSingleton(){} //詳見:http://www.ibm.com/developerworks/cn/java/j-dcl.html public static LockSingleton getInstance(){ if(singleton==null){ synchronized(LockSingleton.class){ if(singleton==null){ singleton=new LockSingleton(); } } } return singleton; }}它在當前的內存模型中無效。 可以看到里面加了volatile關鍵字來聲明單例對象。它有兩層語義。 第一層,可見性。指的是在一個線程中對該變量的修改會馬上由工作內存(Work Memory)寫回主內存(Main Memory),所以會馬上反應在其它線程的讀取操作中。 第二層語義是禁止指令重排序優化。由于編譯器優化,在實際執行的時候可能與我們編寫的順序不同。編譯器只保證程序執行結果與源代碼相同,卻不保證實際指令的順序與源代碼相同。 既然已經起到了多線程下原子性、有序性、可見性的作用, 雙重檢測鎖定失敗的問題并不歸咎于 JVM 中的實現 bug,而是歸咎于 Java 平臺內存模型。內存模型允許所謂的“無序寫入”,這也是失敗的一個主要原因。 還有疑問可參考http://www.iteye.com/topic/652440 和http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
參考: http://www.oschina.net/code/snippet_107039_6062 http://blog.csdn.net/jason0539/article/details/23297037 http://www.cnblogs.com/andy-zhou/p/5363585.html#_caption_5