實戰Java高併發程序設計——單例模式

   單例模式是設計模式中使用最爲普遍的模式之一。它是一種對象創建模式,用於產生一個對象的具體實例,它可以確保系統中一個類只有一個實例。這種模式有一下兩個好處:

1.對於使用頻繁地對象,可以省略new操作花費的時間。特別是對於那些重量級對象而言,能夠節省很多系統開銷。

2.由於new操作的頻率減少,系統內存的使用頻率也會降低。這將減少JVM的GC壓力。

   下面來看一種單例實現

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

   創建單列模式需要注意一下幾點:

  1. 我們要把Singleton類的構造函數設置成private,這是爲了防止開發人員用過構造函數隨意創建這個類的實例。

  2. nstance則必須是private static的,private是爲了防止instance被修改,保證其安全性;static是因爲getInstance()方法是static的。

   使用以上這種實現模式能夠保證該類是單例的,但是這種實現方式有一個不足,那就是instance實例的創健時間是不受控制的。


   如果想要精確控制instance的創健時間,我們可以使用中延遲加載策略,具體實現方式如下:

public class Singleton2{
    private Singleton2(){}
    private static Singleton2 instance = null;
    public static synchronized Singleton2 getInstance(){
        if (instance == null)
            instance = new Singleton2();
        return instance;
    }
}

   使用這種策略就能將instance的實例化推遲到第一次使用Singleton2的時候。注意在getInstance方法上,我們加了synchronized關鍵字,只是爲了防止在多線程下instance被多次創健。因此這種方法的缺點也就暴露出來了,那就是在競爭激烈的場合,其性能肯定會受到影響


   以上兩種方法各有好壞,那有沒有結合上述兩種方法優勢的第三中方法呢?答案肯定是有的。

public class Singleton3{
    private Singleton3{
        System.out.println("Singleton3 is created");
    }
    private static class SingletonHolder{//定義一個靜態內部類來初始化Singleton
        private static Singleton3 instance = new Singleton3();
    }
    public static Singleton3 getInstance(){
        return SingletonHolder.instance;
    }
}

   這種方法有以下2個好處:

  1. getInstance()方法沒有加鎖,在高併發環境下具有高性能。

  2. 只有在getInstance()第一次調用的時候,纔會實例化instance。這是因爲這裏巧妙地使用了靜態內部類和類的初始化方式。

JDK1.8之後,可以使用枚舉類型來實現單例,它具有簡單、懶加載、線程安全、具有高性能等優點。代碼如下:

public enum Singleton{
    INSTANCE;

    public void doSomething(){
        //....
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章