單例模式:
為什么使用單例模式色瘩?
節(jié)約內(nèi)存開銷,提高效率(性能)覆山,提高資源使用率泥栖。
單例模式的特點(diǎn):
構(gòu)造方法私有化
定義靜態(tài)方法返回當(dāng)前對象
確保這個對象是唯一的
確保在序列化和反序列化操作的過程中同樣保證同一個對象簇宽。
列表內(nèi)容
不允許有子類(太監(jiān)類->final)
單例模式->惡漢式(單線程推薦使用)
優(yōu)點(diǎn):安全(為你提前準(zhǔn)備好,不管你用不用)
缺陷:耗費(fèi)內(nèi)存
public final class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
單例模式->懶漢式
優(yōu)點(diǎn):性能高->在一定程度上節(jié)約了內(nèi)存(用到了我才給你吧享,創(chuàng)建)
缺點(diǎn):多線程問題很難解決(并發(fā))Sptring框架魏割、Hebernate框架等等…
問題一:不加鎖?
多線程并發(fā)情況下钢颂,創(chuàng)建多個對象
解決方案:加鎖解決多創(chuàng)建多個對象問題
問題二:阻塞钞它?
200個線程訪問這個對象,等待上一個線程用完了才允許使用(耗費(fèi)性能)
public final class Singleton {
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
單例模式->雙重檢查
優(yōu)勢:既能夠保證創(chuàng)建對象單例對象殊鞭,同時也保證了多線程安全
第一步:分析編譯器編譯過程
以下代碼做了什么事情遭垛?
Singleton instance = new Singleton()
1-首先:分配內(nèi)存(new關(guān)鍵字)
2-其次:調(diào)用構(gòu)造方法初始化參數(shù)
3-最后:將instance對象指向這快內(nèi)存區(qū)域(內(nèi)存空間)
問題:雙重檢查失敗(失效)操灿?
在Java虛擬機(jī)(JVM 1.5之前)中Cache耻卡、寄存器到主內(nèi)存回寫數(shù)據(jù)順序很有可能亂序,有可能是1-2-3牲尺,也有可能是1-3-2卵酪。
1-2-3幌蚊,是先初始化,在指向內(nèi)存
1-3-2溃卡,是先執(zhí)行空內(nèi)存溢豆,在初始化
解決方案
在Java虛擬機(jī)(JVM)1.5版本以及之后版本,做了優(yōu)化關(guān)鍵字volatile (volatile含義:去掉虛擬機(jī)優(yōu)化代碼)瘸羡。
第二步:存在缺陷
為了提高代碼穩(wěn)定性漩仙,程序正確性,消耗性能犹赖。(權(quán)衡)
第三步:這樣的場景下我們可以使用
使用沒有進(jìn)行優(yōu)化過編譯器或者共享內(nèi)存處理器队他,正常運(yùn)行。
單例模式-靜態(tài)內(nèi)部類峻村?->官方推薦使用(多線程推薦使用)
優(yōu)勢:既能夠保證內(nèi)存優(yōu)化麸折,同時也能夠保證安全(單例)
public final class Singleton {
private Singleton(){}
public static Singleton getInstance(){
return SingletonHolder.singleton;
}
public static class SingletonHolder{
private static Singleton singleton = new Singleton();
}
}
單例模式->枚舉
public enum Singleton {
instance;
}