關於單例模式

1、爲何須要單例模式?
能夠保證一個類僅有一個實例,控制實例數目,節約系統的資源。好比:數據庫的鏈接池。一些資源管理器常被設計成單例模式html

2、怎麼使用java

2.1 餓漢式
是否多線程安全:
是否 Lazy 初始化:
描述:
優勢:沒有加鎖,執行效率提升
缺點:在某些狀況下,不是由於調用getInstance而致使的類初始化的話,那麼會存在浪費內存的狀況
該模式是基於classLoader機制避免多線程的問題,當讀取類的靜態字段(類靜態常量不是)、調用類的靜態方法時(固然還有不少狀況會觸發類的初始化,更多細節參考深刻理解JVM虛擬機)。會觸發類的初始化。當進行初始化時,JVM會爲類的靜態語句塊和爲類變量賦值操做,生成<clinit>的彙編指令,該指令保證只有一個線程運行。會阻塞其餘線程,所以能保證只初始化一次。
備註:有人說在類加載時就會初始化,浪費內存,我的感受是不對的。首先JVM的類加載會進行類的加載(加載class文件),驗證(驗證字節碼文件),準備(爲類變量分配內存並賦初值),解析(將符號引號轉爲直接引用);緊接着再初始化,可是須要注意的是,已經說明JVM何時纔會爲類進行初始化。因此,說類在加載時就會初始化,我的感受是不對的。若是我的講述錯誤,請留言數據庫

代碼示例:編程

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
        return instance;  
    }  
}

2.二、靜態內部類
是否多線程安全:
是否 Lazy 初始化:安全

代碼示例:多線程

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE;  
    }  
}

2.三、雙檢鎖/雙重檢驗鎖(DCL,double checked locking)
是否多線程安全:
是否 Lazy 初始化:
描述:
缺點:實現複雜,且效率太低,每次都須要判斷一次if。不推薦使用
請注意
若是singleton變量沒有加上volatile,那麼就是非線程安全的。來模擬一下:
線程A走到④處,初始化完畢了singleton,線程B走到②處。由於沒有加volatile,因此此時singleton可能不會對其餘內存當即可見,因此線程B也走到了④,所以,實例化了2個對象。
代碼示例:併發

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {              ①
        synchronized (Singleton.class) {  ②
        if (singleton == null) {          ③
            singleton = new Singleton();  ④
        }  
        }  
    }  
    return singleton;  
    }  
}

2.四、枚舉
是否多線程安全:
是否 Lazy 初始化:
描述:推薦使用
對於枚舉類來講,每一個對象(INSTANCE)都是被public static final修飾的。其次構造函數默認私有。因此用來實現單例模式,是很是適合的。
在Effective Java第二版的第77條,推薦使用枚舉實現單例模式。
代碼示例:函數

public enum Test{  
    INSTANCE;  
    private Singleton singleton;
    Test() {
        singleton = new Singleton;
    }
    public Singleton getInstance() {
        return singleton;
    }
}

有關參考:
java併發編程實戰
EffectiveJava 第二版
http://www.runoob.com/design-...線程

相關文章
相關標籤/搜索