設計模式之【單例模式】
阿新 • • 發佈:2017-07-04
sta 嵌套 mem ont volatile 單例對象 locate 頂級 調用 2 3的重排序。
Class被加載後,且被線程使用之前),會執行類的初始化。在執行類的初始化期間,JVM會去獲取一個鎖。這個鎖可以同步多個線程對同一個類的初始化。
完美的單例
雙重檢查鎖(DCL)
用處:延遲初始化,降低同步開銷。double checked locking
註意:single必須聲明為volatile,且支持JDK1.5及以上版本。
對象初始化需要三個步驟:
memory=allocate(); //1.分配內存空間
ctorInstance(memory) //2.初始化對象
instance=memory //3.設置對象指向分配的內存
如果single不是volatile的話,那麽處理器會有可能重排序2 3步驟,導致多線程並發時得到實例已經分配內存空間,但並未初始化。
Volatile保證了單例對象的原子性、可見性,禁止了步驟
public class Singleton { private volatile static Singleton single; private Singleton(){ } public static Singleton getInstance() { if(single==null){ synchronized(Singleton.class){ if(single==null){ single=new Single(); } } } return single; } }
靜態內部類單例
好處:JVM在類的初始化階段(即在
基於類初始化鎖【是類的初始化,並非對象初始化】的特性,可以以靜態內部類的方式實現延遲初始化單例:
public class Singleton { private static class SingletonHolder{ public static Singleton single = new Singleton(); } private Singleton(){ } public static Singleton getInstance() {return SingletonHolder.single; } }
初始化一個類,包括執行這個類的靜態初始化和初始化這個類中聲明的靜態字段。根據JAVA規範,當發生如下情況,將初始化一個類:
T是一個類,且T類的一個實例被創建;
T是一個類,且T類中聲明的一個靜態方法被調用;
T中聲明的一個靜態字段被賦值;
T中聲明的一個靜態字段被使用,且這個字段不是一個常量字段;
T是一個頂級類,而且一個斷言語句嵌套在T內部被執行。
枚舉
枚舉是天生的單例。
設計模式之【單例模式】