常用設計模式——單例模式

個人整合學習自

  1. 《Java設計模式》 劉偉 編著

單例模式

Singleton Pattern:確保一個類職業一個實例,並提供一個全局訪問點來訪問這個唯一實例。也是一直創建型模式。

單例模式的三個要點:

  1. 某個類只能有一個實例;
  2. 它必須自行創建這個實例;
  3. 它必須自行向整個系統提供這個實例。

實現

1. 餓漢式單例

package xyz.cglzwz.designpattern.sp;

/**
 * 餓漢式單例
 * @author chgl16
 * @date 2019-04-02
 */

public class EagerSingleton {
	private static final EagerSingleton instance = new EagerSingleton();
	
	private EagerSingleton() {}
	
	public static EagerSingleton getInstance() {
		return instance;
	}
}

當類加載時,靜態變量instance會被初始化,此時類的私有構造函數會被調用,單例類的唯一實例將被創建。(叫餓漢是eager的意思,渴望第一時間加載)

  • 優點:無需考慮多線程同時訪問的問題,可以確保實例的唯一性,而且調用速度和反應時間比以下的懶漢模式要優。
  • 缺點:類加載時就創建,加載時間可能比較長。

2. 懶漢式單例

package xyz.cglzwz.designpattern.sp;

/**
 * 懶漢式單例模式
 * 
 * @author chgl16
 * @date 2019-04-02 
 */

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

懶漢式都是在第一次調用getInstance()方法時初始化實例,在類加載時並不自行創建,這種技術也稱爲延遲加載(Lazy Load)技術。

上面代碼雖然增加了synchronized修飾符進行線程隱式鎖定,解決了線程安全問題。但是多線程高併發訪問環境還是會大大降低系統性能。因此可以代碼優化下,因爲這裏可見只需對 instance = new LazySingleton(); 鎖定即可。如下改進

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

問題貌似解決,但是並非如此。如果多個線程都同時到了 "if (instance == null) "爲 true的情況,都通過了判斷,由於事先了synchronized加鎖機制,只是某一個線程創建了對象。但是後面的線程不知道,會繼續創建的(因爲已經通過判斷了)。

繼續改進,使用雙重檢查鎖定

package xyz.cglzwz.designpattern.sp;

/**
 * 懶漢模式雙重檢查鎖定
 * @author chgl16
 * @date 2019-04-03
 */
public class LazySingleton2 {
    // 使用volatile修飾,確保每個線程能夠正確處理
	private volatile static LazySingleton2 instance = null;
	
	private LazySingleton2() {}
	
	public static synchronized LazySingleton2 getInstance() {
		// 第一重判斷
		if (instance == null) {
			// 鎖定代碼塊
			synchronized (LazySingleton2.class) {
				// 第二重判斷
				if (instance == null) {
					// 創建單例實例
					instance = new LazySingleton2();
				}
			}	
		}
		return instance; 
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章