咱們經過單例模式能夠保證系統中一個類只有一個實例並且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。若是但願在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。安全
public class Singleton { private static final Singleton instance = new Singleton(); private Singleton(){ } public Singleton getSingleton(){ return instance; } }
該類的構造方法被private修飾,外部訪問者只能經過getSingleton方法得到實例,而不能本身再建立實例,能夠保證系統中只有一個實例,不足之處在於,該類在被加載時就實例化了一個對象,而無論其將在什麼時間用到,所以咱們要考慮延遲等到真正須要時建立實例,請看下面的第二種方法:spa
該實例有用戶經過一個線程安全的方法去建立,以下所示:線程
public class Singleton { private static Singleton instance = null; private Singleton() { } public static synchronized Singleton getSingleton() { if (instance == null) { return new Singleton(); } else { return instance; } } }
這種方式經過一個線程安全的方法,來獲得一個實例,但每一個線程獲取該實例時都要訪問線程同步的方法,申請對象鎖、得到對象、釋放所持有的對象鎖,通過這一些列的操做後,其它線程纔可以獲得實例。實際上只須要在建立實例時須要線程安全,獲得這個實例其實就不須要維護線程安全開銷了,爲此能夠利用下面的方式:code
public class Singleton { private static volatile Singleton instance; private Singleton() { } public static Singleton getSingleton() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
咱們對instance變量用volatile關鍵字修飾,以確保一個線程更改爲員變量後,其它線程可以看到更改後的變量,也就是專業術語中的「可見性」,同時,咱們對getSingleton方法進行了改進,當且僅當建立實例時才進行同步,去獲取實例時並無同步,以減小獲取實例時的開銷。對象