1. 程式人生 > >高效能的執行緒安全單例——Java基礎語法系列

高效能的執行緒安全單例——Java基礎語法系列

大家都知道,一般實現單例有兩種寫法: 餓漢式 和 懶漢式, 餓漢式是執行緒安全的,在編譯期間已完成初始化,載入到了記憶體裡。 懶漢式一般寫法是非執行緒安全的, 那懶漢式的執行緒安全單例應該如何實現呢,以及如何寫出低耗能的執行緒安全單例呢 ?

單例實現關鍵點

  • 建構函式私有,private
  • 例項物件 靜態 且 私有
  • 公開獲取例項的靜態方法

下面我們直接上程式碼了,按重要程度排序,提供三種方式:

一、高效能的執行緒安全單例 - 懶漢式

關鍵注意點:

  • volatile 關鍵字修飾例項物件, 禁止指令重排序
  • 加鎖例項初始化過程
  • 判斷例項物件為空時,進行雙重校驗
package safe;

/**
 * @description 執行緒安全的單例——懶漢式載入
 * @author [email protected]
 * @date 2018/11/20
 */
public class LazySingleton {
    /**
     * volatile 修飾屬性,簡直指令重排序
     */
    private static volatile LazySingleton lazySingleton = null;

    private LazySingleton() {
        //模擬: 建立執行緒為耗時操作
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static LazySingleton getInstance()  {
    	// 雙重校驗
        if (null == lazySingleton) {
            synchronized(LazySingleton.class) {
                if (lazySingleton == null) {
                    lazySingleton = new LazySingleton();
                }
            }
        }
        return lazySingleton;
    }

    public static void main(String args[]) {
        for (int i = 0; i < 10; i ++) {
            new Thread(() -> {
                System.out.println(LazySingleton.getInstance());
            }).start();
        }
    }
}

二、執行緒安全單例 - 懶漢式

同樣是懶漢式,但是這次實現的方式不一樣,我們直接選擇在 獲取例項的方法上,加上同步鎖, 但是缺點就是有點消耗效能。

package safe;

/**
 * @description 執行緒安全的單例-懶漢-消耗效能
 * 將 Sychronized 關鍵字載入方法上,消耗效能
 * @author [email protected]
 * @date 2018/11/20
 */
public class LazySingleton_SyncMethod {
    private LazySingleton_SyncMethod() {}
    private static LazySingleton_SyncMethod instance = null;
    public static synchronized LazySingleton_SyncMethod getInstance() {
        if (instance == null) {
            instance = new LazySingleton_SyncMethod();
        }
        return  instance;
    }

    public static void main(String args[]) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println(LazySingleton_SyncMethod.getInstance());
            }).start();
        }
    }
}

三、執行緒安全單例-餓漢式

編譯期間,直接完成了初始化。

package safe;

/**
 *
 * @description  餓漢單例
 * @author [email protected]
 * @date 2018/11/20
 */
public class HungerSingleton {
    private static HungerSingleton ourInstance = new HungerSingleton();

    public static HungerSingleton getInstance() {
        return ourInstance;
    }

    private HungerSingleton() {
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                System.out.println(HungerSingleton.getInstance());
            }).start();
        }
    }
}