JAVA單例類的線程安全最簡潔有效的寫法

平時使用單例的情況很多,至於爲什麼使用在此文章中就不在重複,百度、谷歌一大堆。而單例模式分爲立即加載和延遲加載兩種,這兩種在多線程下都存在安全問題,因此很多時候我們會使用sychronized關鍵字或者代碼塊來保證我們的單例是線程安全的。


本文向各位推薦一種美觀而簡潔,並且線程安全的寫法。

目標:

  1. 延遲加載

  2. 由於方法同步會降低效率,因此要提高效率(通常做法會使用雙檢查[Double-Check],即先判斷單例對象是否爲空,如果爲空則才進入sychronized代碼塊來對單例對象進行實例化),提高同步的效率

  3. 不使用sychronized代碼塊或者關鍵字

原理:

  1. 延遲加載這個就是我們調用getInstance方法的時候,纔對單例對象進行初始化或者直接返回,我們使用內部類來作爲延遲加載的解決辦法

  2. 我們不需要進行手工的判斷是否需要去實例化該單例,保證我們的內存中確實只有一個實例存在

  3. 初始化內部類的時候,JLS(Java Language Sepcification)會保證這個類的線程安全

代碼:

package com.troy.young.thread;
/**
 * 線程安全的單例類
 *
 * @author Administrator
 *
 */
public class SingleTon {
    /**
     * 定義他的構造方法,讓外部沒有辦法是用new去構造該對象
     */
    private SingleTon() {
    }
    /**
     * 定義內部類對單例進行實例化。
     * 首先內部類是static的,保證了該類在內存中只有一份,同時他的成員變量是final static的,則又再次保證他的單一性。
     * 同時由於JLS會保證類的線程安全。
     * @author Administrator
     *
     */
    private static class SingleTonHolder {
        public final static SingleTon instance = new SingleTon();
    }
    /**
     * 提供獲取實例的方法
     * @return
     */
    public static SingleTon getInstance() {
        // 直接獲取內部類的變量
        return SingleTonHolder.instance;
    }
}

到此我們可以看到,這個代碼既簡潔有安全,可以放在我們的項目中作爲一個嘗試。

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