設計模式(一):單例模式

一. 單例模式 基本概念
二. 單例模式與多線程

一. 單例模式 基本概念
        單例模式就是在應用程序中只創建一個該類的對象。又分爲餓漢模式和懶漢模式。實現套路也就是只提供私有構造函數,然後提供公有的 getInstance 方法。
  • 餓漢模式:也就是一開始就創建該對象。
  • 懶漢模式:等到需要用到的時候才創建該對象。
懶漢模式:
public class Singleton {
	private static Singleton singleton;
	
	private Singleton(){};
	
	/**
	 * 
	 * getInstance:返回單例. <br/> 
	 * 
	 * @author whc 
	 * @return 
	 * @since JDK 1.8
	 */
	public static Singleton getInstance(){
		if(singleton == null)
			singleton = new Singleton();
		
		return singleton;
	}
}

餓漢模式:
public class Singleton {
	private static Singleton singleton = new Singleton();
	
	private Singleton(){};
	
	/**
	 * 
	 * getInstance:返回單例. <br/> 
	 * 
	 * @author whc 
	 * @return 
	 * @since JDK 1.8
	 */
	public static Singleton getInstance(){
		return singleton;
	}
}

二. 單例模式與多線程
        其實上面的例子只能使用在單線程下,無法應對多線程環境。比如說如果線程A,B 同時訪問到 if(singleton == null) ,那麼結果就會創建兩個實例,這樣就不符合單例模式的思想。

改進1:
        此時我們最容易想到 synchronized 關鍵,這也是最簡單的多線程處理,加個關鍵字完事了,如下:
public static synchronized Singleton getInstance(){
    if(singleton == null)
		singleton = new Singleton();
		
	return singleton;
}

        此時確實能解決問題,但是效率不高,比如說,無論這個對象存不存在,那麼都需要加鎖解鎖,但是道理上應該是創建完後就不需要加鎖了。所以有以下改進2。

改進2:

public class Singleton {
	private static Singleton singleton;
	private static Lock lock = new ReentrantLock();
	
	private Singleton(){};
	
	/**
	 * 
	 * getInstance:返回單例. <br/> 
	 * 
	 * @author whc 
	 * @return 
	 * @since JDK 1.8
	 */
	public static Singleton getInstance(){
		if(singleton == null){
			lock.lock();
			try {
				if(singleton == null){
					singleton = new Singleton();
				}
			} finally{
				lock.unlock();
			}
		}
		
		return singleton;
	}
}

總結:
  • 基本概念:分餓漢,懶漢模式。實現:只提供私有構造函數 與 getInstance 方法。
  • 普通的單例模式的實現不支持多線程環境,若需支持則要結合 synchronized 或者 lock 等多線程處理方式。

參考:
1. 《劍指 Offer》。
發佈了97 篇原創文章 · 獲贊 19 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章