設計模式學習筆記:單例模式

1、概念

通常採用單例模式就是爲了知足「只建立一個類」的須要。安全

單例模式有兩個特色:
(1)一個類僅有一個實例
(2)僅有一個全局訪問點線程

2、寫法

一、餓漢式
所謂餓漢式,是指這個類的實例在類加載階段就已經建立出來了。code

public class Singleton1 {
    //在類的內部實例化一個實例
    private static final Singleton1 instance = new Singleton1();
    //隱藏構造方法
    private Singleton1() {
    }
    //對外開放一個獲取實例的方法
    public static  Singleton1 getInstance(){
        return instance;
    }
}

固然也可使用static代碼塊。(注意這裏的final,看網上有各類寫法,加或者不加的都有,我認爲這裏能夠加,這樣getInstance方法裏就不須要判空了)對象

這種方式雖然可以有效避免線程安全的問題,可是卻可能形成沒必要要的浪費,由於也許這個實例並不須要用到,或者就用到一兩次,卻要一直佔用內存。內存

二、靜態內部類get

public class InnerClassSingleton {
    //在靜態內部類中實例化對象
    private static class SingletonHolder{
        private static final InnerClassSingleton instance = new InnerClassSingleton();
    }
    //隱藏構造方法
    private InnerClassSingleton(){
    }
    //對外提供訪問方法
    public static final InnerClassSingleton getInstance() {
        return SingletonHolder.instance;
    }
}

三、懶漢式
所謂懶漢式,就是在使用時才加載,比較「懶一些」。class

public class Singleton2 {
    private static Singleton2 instance;
    private Singleton2(){
    }
    public static Singleton2 getInstance(){
        //在對象被使用時才實例化
        if (instance == null)
            instance = new Singleton2();
        return instance;
    }
}

注意:加上synchronized關鍵字就能夠保證線程安全。效率

public class Singleton2 {
    private static Singleton2 instance;
    private Singleton2(){
    }
    public static synchronized Singleton2 getInstance(){
        //在對象被使用時才實例化
        if (instance == null)
            instance = new Singleton2();
        return instance;
    }
}

四、固然上述方式效率比較低,由於synchronized鎖的範圍太大了程序

public class Singleton2 {
    private static Singleton2 instance;
    private Singleton2(){
    }
    public static Singleton2 getInstance(){
        //在對象被使用時才實例化
        synchronized (Singleton2.class){
            if (instance == null)
                instance = new Singleton2();
            return instance;
        }
    }
}

這樣就縮小了鎖的範圍,可是這種方式依然存在問題,由於Java內存模型的機制,程序可能會崩潰,所以就要用到volatile。方法

五、使用volatile

public class Singleton2 {
    private static volatile Singleton2 instance;
    private Singleton2(){
    }
    public static Singleton2 getInstance(){
        //在對象被使用時才實例化
        if (instance == null){
            synchronized (Singleton2.class){
                if (instance == null)
                    instance = new Singleton2();
                return instance;
            }
        }
    }
}

六、枚舉式

public enum  Singleton3 {
    INSTANCE;
    Singleton() {
    }
}
相關文章
相關標籤/搜索