創建型_單例模式(Singleton Pattern)

基本概念

  1. 意圖:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點
  2. 主要成分:
    a. 私有靜態成員變量
    b. 私有構造器
    c. 公有靜態get方法
  3. UML圖
    在這裏插入圖片描述

實現方法

餓漢模式

tip1:在類準備階段中實現變量初始化,直接通過get方法獲取初始化後的類變量

class Singleton{
	private static Singleton instance=new Singleton();
	private Singleton() {}
	
	public static Singleton getInstance() {
		return instance;
	}
}
懶漢模式
  1. 非線程安全版本
    tip1:只適用於單線程,多線程不適用

    多線程不適用的原因:
    step1:初始instance爲null
    step2:多個線程同時訪問getInstance()方法
    step3:多個線程的條件判斷都滿足(即instance等於null),於是創建了兩個或多個Singleton對象
    summary:非線程安全版本在多線程時,違背了Singleton模式的初衷
class Singleton{
	private static Singleton instance=null;
	
	private Singleton() {}
	public static Singleton getInstance() {
		if(instance==null) {
			instance=new Singleton();
		}
		return instance;
	}
}
  1. 線程安全版本
    tip1:對getInstance()加鎖
    tip2:鎖的代價過高(多個線程同時讀,沒必要加鎖),因此不適用於高併發的情況,如Web開發

    實現多線程的流程:假設有多個線程A、B…
    step1:初始instance爲null
    step1:多個線程同時訪問getInstance()方法
    step2:最先訪問的線程A先向下執行,並對getInstance()方法 加鎖,此時其他線程無法向下執行
    step3:線程A中符合條件instance等於null,調用構造器,instance不等於空
    step4:…直到線程A釋放鎖,其他方法才能使用getInstance()方法
class Singleton{
	private static Singleton instance=null;
	
	private Singleton() {}
	public static Singleton getInstance() {
		synchronized (Singleton.class) {
			if(instance==null) {
				instance=new Singleton();
			}
		}
		return instance;
	}
}
  1. 雙檢查鎖(double check)
    tip1:鎖前檢查,避免了線程安全版本代價過高的問題
    tip2:鎖後檢查,避免了多個線程創建多個對象的問題

    對於instance=new Singleton();語句,在計算機中的實現可分爲如下3個步驟
    stepA:分配內存
    stepB:調用構造器,對分配的內存進行初始化
    stepC:將內存的地址給instance
    但是由於內存讀寫reoder(重排列優化問題)不安全,使得該實現步驟出現stepA、stepC、stepB的情況
    從而使得多個線程的instance僅僅拿到一個原生的地址(即不含內容)
class Singleton{
	private static Singleton instance;
	
	private Singleton() {}
	public static Singleton getInstance() {
		if(instance==null) {//鎖前檢查
			synchronized (Singleton.class) {
				if(instance==null) {//鎖後檢查
					instance=new Singleton();
				}
			}
		}
		return instance;
	}
}
  1. 改進的雙檢查鎖
    tip1:對變量instance增加volatile聲明。表示編譯器不能對其進行優化,則可以保證instance的整個構造過程按stepA、stepB、stepC順序執行
class Singleton{
	private static volatile Singleton instance;
	
	private Singleton() {}
	public static Singleton getInstance() {
		if(instance==null) {
			synchronized (Singleton.class) {
				if(instance==null) {
					instance=new Singleton();
				}
			}
		}
		return instance;
	}
}

12


  1. Singleton模式中構造器可以設置爲protected,以允許子類派生 ↩︎

  2. Singleton模式一般不要支持拷貝構造函數和Clone接口,因爲這可能導致多個對象實例,與Singleton模式的初衷相違背 ↩︎

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