java單例類的幾種實現

來源:互聯網
上載者:User

標籤:span   構造   vat   實現   擷取   影響   最佳化   第一個   關鍵字   

一,最簡單的方式
public class Singleton{    private Singleton(){};    private static Singleton instance = new Singleton();    public static Singleton getInstance(){        return instance;    }}

首先建構函式聲明為private,防止被外部建立該類的執行個體。聲明一個static的成員變數instance並分配執行個體,當Singleton類被載入時,instance便會被建立,可以通過靜態方法getInstance方法擷取到該執行個體。
優點是實現簡單,且沒有安全執行緒問題。缺點是Singleton被引用時instance執行個體就已經建立,即使執行個體並沒有用到。

二,懶載入的單例類
public class Singleton{    private Singleton(){};    private static Singleton instance = null;    public static synchronized Singleton getInstance(){        if(instance == null){            instance = new Singleton();        }        return instance;    }}

因為instance初始值為null,所以在Singleton被載入的時候,並不會執行個體化,只有調用getInstance方法的時候才會建立執行個體。為了防止多線程並發調用getInstance方法時instance被多次建立,所以使用synchronized關鍵字進行線程同步。
該實現缺點是,每次調用getInstance方法都要進行線程同步,影響並發量。

三,改進懶載入的單例類
public class Singleton{    private Singleton(){};    private static volatile Singleton instance = null;    public static Singleton getInstance(){        if(instance == null){            synchronized(Singleton.class){                if(instance == null){                    instance = new Singleton();                }            }        }        return instance;    }}

通過雙檢索的方式進行最佳化,只有在intance沒有值時才進行線程同步,此後會直接返回執行個體。需要注意的是,在synchronized代碼塊中需要再判斷一次instance是否為null,防止多個線程同時通過了第一個為null的判斷。
還需要注意的是,instance需要volatile修飾,防止指令重排序導致的錯誤。
volatile除了保證線程緩衝及時同步到主記憶體並清理其他線程緩衝的值,還有一個作用就是防止指令重排序。 instance = new Singleton() 這行代碼編譯後會拆分成三個指令,可以理解成如下代碼:
1,Singleton temp = malloc(); // 分配記憶體
2,constructor(temp); // 調用建構函式對分配的記憶體進行初始化
3,instance = temp; // 初始化完成的記憶體位址賦值給instance
編譯器為了最佳化指令,重排序後,可能會變成了下面的代碼:
1,Singleton temp = malloc(); // 分配記憶體
2,instance = temp; // 初始化完成的記憶體位址賦值給instance
3,constructor(instance); // 調用建構函式對分配的記憶體進行初始化
如果代碼執行了上面的第二步,instance已經賦值不為null,但並沒有初始化,這是如果第二個線程調用getInstance方法就會直接獲得instance,調用instance時引發錯誤。volatile可以防止重排序。

四,通過內部類實現單例
public class Singleton{    private static class SingletonHolder{        private static Singleton instance = new Singleton();    }    private Singleton(){};    private static volatile Singleton instance = null;    public static Singleton getInstance(){        return SingletonHolder.instance;    }}

Singleton的執行個體被靜態內部類SingletonHolder持有,只有在調用getInstance方法時,SingletonHolder才會被載入,instance被執行個體化。既實現懶載入,也不會有安全執行緒問題。

 

java單例類的幾種實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.