堅持每天寫博文,記錄開發中的點點滴滴
- 餓漢式
餓漢式
餓漢式可以說是我們最先接觸單例模式的例子了,是最基本的單例寫法,也是最快最懶的方式。
優點:簡單好寫;缺點:類加載就初始化了對象,影響應用啓動速度
package singleton;
/**
*
* @ClassName: BaseSingleton
* @Description: TODO(餓漢式單例模式)
* @author Allen
* @date 2018年1月11日 上午10:08:13
*
*/
public class BaseSingleton {
//第一步:私有構造
private BaseSingleton() {
}
//第二步,私有靜態對象
private static BaseSingleton INSTANCE = new BaseSingleton();
//第三步:提供對外獲取方法
public static BaseSingleton getBaseSingleton() {
return INSTANCE;
}
}
- 懶漢式 主要是針對於餓漢式的缺點
優點:只有第一次使用時纔會初始化對象;缺點:多線程中可能出現創建多個對象
其實就是加了個空判斷
package singleton;
/**
*
* @ClassName: LazyLoadSingleton
* @Description: TODO(懶漢式單例)
* @author Allen
* @date 2018年1月11日 上午10:17:27
*
*/
public class LazyLoadSingleton {
//第一步:私有構造
private LazyLoadSingleton() {
}
//第二步:私有靜態對象
private static LazyLoadSingleton INSTANCE;
//第三步:如果存在實例給出獲取方法,不存在創建
public LazyLoadSingleton getLazyLoadSingleton() {
if(INSTANCE == null) {
INSTANCE = new LazyLoadSingleton();
}
return INSTANCE;
}
}
- 同步鎖式
因爲懶漢式的出現,雖然解決了餓漢式的不足,但也出現了多線程的問題。於是解決懶漢式的方式就出現了,那就是我們熟知的加鎖Synchronized。
優點:保證線程安全;缺點:每次都要加鎖,但是獲取不經濟。
package singleton;
/**
*
* @ClassName: LazySynchronizedSingleton
* @Description: TODO(同步鎖式單例)
* @author Allen
* @date 2018年1月11日 上午10:24:02
*
*/
public class LazySynchronizedSingleton {
//第一步:私有構造
private LazySynchronizedSingleton() {
}
//第二步:創建私有對象
private static LazySynchronizedSingleton INSTANCE;
//第三步:提供一個同步的對外獲取方法
public static synchronized LazySynchronizedSingleton getInstance() {
if(INSTANCE == null) {
INSTANCE = new LazySynchronizedSingleton();
}
return INSTANCE;
}
}
- 雙重檢測式
第3種方式應該已經滿足日常大部分的需求,但對我們程序員來說,不斷的優化纔是學習之道。那麼針對每次獲取都會加鎖的問題,要怎麼解決呢?雙重檢測式就出現了。
優點:第一次獲取時纔會加鎖;缺點:相比之下寫法麻煩
package singleton;
/**
*
* @ClassName: DoubleCheckSingleton
* @Description: TODO(雙重檢測單例模式)
* @author Allen
* @date 2018年1月11日 上午10:29:39
*
*/
public class DoubleCheckSingleton {
//第一步:私有構造
private DoubleCheckSingleton() {
}
//第二步:創建靜態對象
private static volatile DoubleCheckSingleton INSTANCE;
//提供對外方法
public static DoubleCheckSingleton getInstance() {
if(INSTANCE == null) {
synchronized (DoubleCheckSingleton.class) {
if(INSTANCE == null) {
INSTANCE = new DoubleCheckSingleton();
}
}
}
return INSTANCE;
}
}
我們第二步用到了volatile,關於volatile不是本文的重點,所以這裏不展開說明。在第三步中,我們首先判斷一次空,如果是空,就加鎖,然後再判斷一次空,如果爲空就創建。這樣的好處就是上面優點說到的,只會鎖一次。缺點大家也發現了,不僅要必須寫volatile,方法中的步驟也不能錯。
Java中Volatile關鍵字詳解 https://www.cnblogs.com/zhengbin/p/5654805.html
- 內部類式
優點:懶加載、線程安全、代碼少;缺點:暫無
內部類Holder,裏面有外部的實例。這怎麼就滿足懶漢式和線程安全呢?當我們應用初始化時,getInstance沒有被調用,就沒有實例對象,那就滿足了懶漢式。當我們調用getInstance的時候,Java虛擬機爲了保證類加載的安全性,所以這裏就保證了線程安全。
整理自:詳細的雙語言(Java與Kotlin)5種單例模式 2018-01-08 FYNN_JASON 碼個蛋