一篇文章講清楚單例模式

前言:

做者:韓數html

Github:github.com/hanshuaikan…java

時間:2019-01-26git

Jdk版本:1.8github

定義:

保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。設計模式

適用範圍:

一個全局使用的類頻繁地建立與銷燬。當某些如打印機程序只須要一個操做實例的時候(多個實例同時調用一臺打印機打印文件可能會出現問題)緩存

優/缺點

優勢:安全

在內存裏只有一個實例,減小了內存的開銷,尤爲是頻繁的建立和銷燬實例(好比管理學院首頁頁面緩存)。多線程

避免對資源的多重佔用(好比寫文件操做)性能

缺點:spa

沒有接口,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化

前提引入:

單例模式是設計模式中較爲簡單的設計模式之一,同時又在實際的開發過程當中普遍使用的一種設計模式,本次,咱們將從基礎版開始,使用4種不一樣的方式來實現單例模式。

代碼實戰:

1.基礎版

這種方式實現的單例模式是咱們平常使用較多的設計模式,採用了延遲加載來減小系統資源沒必要要的開支,但若是多個線程同時調用 getInstance 方法獲取Singleton的實例時,可能會出現問題。

優/缺點:

優勢:易於實現

缺點:線程不安全,在多線程下不能正常工做

代碼以下:

/*** * * @author 韓數 * 通常單例模式實現,採用延遲加載方式實現 * */

public class Singleton {
	
	private static Singleton uniqueInstance;
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
 
}
複製代碼

2.線程安全基礎版:

代碼以下:

優/缺點:

優勢:線程安全,沒有加鎖,執行效率會高一點

缺點:容易產生垃圾對象,類加載時就初始化,浪費內存

/*** * * @author 韓數 * 經常使用的單例模式實現 * 線程安全,不足之處,可能會損失一部分性能,非延遲加載 * */


public class Singleton {
	
	//在類初始化的時候就實例化對象,因此不存在多線程的安全問題
	private static Singleton uniqueInstance = new Singleton();
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		return uniqueInstance;
	}
}
複製代碼
3.線程安全增強版:

優/缺點:

優勢:線程安全,延遲加載

缺點:必須加鎖,效率比較低

代碼以下:

/** * * @author 韓數 * 線程安全方式實現單例模式,缺點是,每次都會調用synchronized的關鍵字修飾的方法,會損失必定的性能 * */

public class Singleton {
	
	
	private static Singleton uniqueInstance;
 
	private Singleton() {}
 
	//synchronized修飾該方法,保證每次只有一個線程進入該方法,從而避免產生多個Singleton對象實例。
	public static synchronized Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
}

複製代碼
4.線程安全旗艦版:

雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking): 能夠在保證安全性的狀況下,兼顧高性能

優/缺點:

優勢:線程安全,延遲加載,執行效率高

缺點:實現難度比前幾種稍顯複雜

關於 volatile 關鍵字,感興趣的夥伴能夠去這個博客看一下,寫得很是好

www.cnblogs.com/dolphin0520…

代碼以下:

/*** * * @author 韓數 * 線程安全,延遲加載方式實現單例模式 * */

public class Singleton {
	
	private volatile static Singleton uniqueInstance;
	
	// 一旦一個共享變量(類的成員變量、類的靜態成員變量)被volatile修飾以後,那麼就具有了兩層語義:
	//保證了不一樣線程對這個變量進行操做時的可見性,即一個線程修改了某個變量的值,這新值對其餘線程來講是 當即可見的。
	//禁止進行指令重排序。
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		//延遲加載
		if (uniqueInstance == null) {
			//加線程鎖
			synchronized (Singleton.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}
}

複製代碼

總結:

本篇文章較爲簡單的闡述了單例模式的優缺點,使用場景,以及4種不一樣的實現方式,固然,現實生活中,單例模式的實現絕非只有本文中的4種,若是對單例模式的其餘實現方式感興趣的話,你們能夠去互聯網上查詢相關的資料。

寫在最後:

歡迎你們給小星星,您的星星是我寫下去的不竭動力!

源碼部分請移步本人Github下載:

Github地址:

Github:github.com/hanshuaikan…

參考資料:

菜鳥教程:www.runoob.com/design-patt…

Head frist of 設計模式

相關文章
相關標籤/搜索