問題引入java
有時候對於有些對象,咱們只須要一個,多了反而會出現不少問題。好比:線程池,緩存,處理器偏好設置,日誌對象等等(可能致使程序異常,內存泄露)。
程序員
模式定義緩存
確保一個類只有一個實例,並提供一個全局訪問點。安全
認識模式多線程
確實咱們能夠經過程序員之間的約定保證一個類只有一個對象,可是經過使用單例模式效果更好,更安全。函數
問題解決spa
建立單例模式類步驟: .net
* 一、構造一個私有的靜態變量;線程
* 二、構造函數私有化,避免外部直接建立對象;日誌
* 三、建立一個公有的靜態方法,返回該變量,若是該變量爲空,建立該對象。
直接上代碼:
package my.oschina.net.design.singleton; class SingleTon { private static SingleTon instance = null; private SingleTon(){} public static SingleTon getInsatnce() { if(null == instance) instance = new SingleTon(); return instance; } }
這是一個經典的單例模式代碼,可是它自己是有問題的,在多線程的狀況下,可能會出現多個對象。因而咱們作以下的改進
class SingleTon { private static SingleTon instance = null; private SingleTon(){} public static synchronized SingleTon getInsatnce() { if(null == instance) instance = new SingleTon(); return instance; } }
咱們給這個方法加上同步機制,這樣就不存在多線程的問題了,可是新的問題來了,實際上只有在第一次執行這個方法的時候才須要同步,之後實際上就不須要同步。可是這樣寫代碼,咱們每調用一次都須要同步,這顯然是很費時費事的。因而咱們再進行改進。
class SingleTon { private static SingleTon instance = null; private SingleTon() {} public static SingleTon getInstance() { if (null == instance ) { synchronized (SingleTon.class) { if (null == instance) { SingleTon = new Siglenton(); } } } return instance ; } }
這個就好多了,咱們稱這個爲雙重檢查(DOUBLE-CHECKED),咱們先檢查對象是否已經建立,若是沒有建立咱們在進行同步,這樣一來只有第一次會同步,恰好符合咱們的要求。
上面所說的咱們都稱他爲「懶漢模式」,咱們延遲了對象的實例化,下面咱們看看所謂的"餓漢模式」
class Singleton { private static Singleton instance= new Singleton(); //能夠保證線程安全 private Singleton() {} public static Singleton getInstance() { return instance; } }
還有一種使用靜態內部類的方法
public class Singleton { private static class SingletonHolder { private static final Singleton instance= new Singleton(); } private Singleton() {} public static final Singleton getInstance() { return SingletonHolder.instance; } }