
所謂類的單例設(shè)計(jì)模式,就是采取一定的方法保證在整個(gè)的軟件系統(tǒng)中,對(duì)某個(gè)類只能存在一個(gè)對(duì)象實(shí)例,并且該類只提供一個(gè)取得其對(duì)象實(shí)例的方法(靜態(tài)方法)
Spring 中的 bean 默認(rèn)都是單例模式,每個(gè)bean定義只生成一個(gè)對(duì)象實(shí)例,每次 getBean請(qǐng)求獲得的都是此實(shí)例
二 單例模式八種方式單例模式的八種實(shí)現(xiàn)方式,如下所示
class Singleton {//一:構(gòu)造器的私有化 防止外部用構(gòu)造器...
private Singleton() {}
//二:類的內(nèi)部創(chuàng)建對(duì)象 final static
private static final Singleton singleton = new Singleton();
//三:對(duì)外提供公共的靜態(tài)方法 返回該類唯一的對(duì)象實(shí)例
public static Singleton getInstance() {return singleton;
}
}案例分析//案例演示 - 餓漢式
public class SingletonDemo {public static void main(String[] args) {// 方式一:靜態(tài)常量
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1); //true
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
通過(guò)結(jié)果可以發(fā)現(xiàn)返回的是同一個(gè)對(duì)象所以單例模式是實(shí)現(xiàn)的。
寫法分析優(yōu)勢(shì): 簡(jiǎn)單 避免多線程的同步問(wèn)題劣勢(shì): 沒(méi)有達(dá)到懶加載的效果 內(nèi)存的浪費(fèi)
//方式二:靜態(tài)代碼塊的方式
class Singleton {//構(gòu)造器私有化
private Singleton() {}
//類的內(nèi)部創(chuàng)建對(duì)象
private static final Singleton singleton;
static {singleton = new Singleton();
}
//對(duì)外提供公共的靜態(tài)的方法
public static Singleton getInstance() {return singleton;
}
}案例分析優(yōu)勢(shì): 簡(jiǎn)單 避免多線程的同步問(wèn)題劣勢(shì): 沒(méi)有達(dá)到懶加載的效果 內(nèi)存的浪費(fèi)
class Singleton{//構(gòu)造器私有化
private Singleton(){}
//類的內(nèi)部提供對(duì)象
private static Singleton singleton;
//對(duì)外提供公共的靜態(tài)方法的時(shí)候,來(lái)判斷
public static Singleton getInstance(){if (singleton == null){singleton = new Singleton();
}
return singleton;
}
}案例分析優(yōu)勢(shì):起到了懶加載的效果 不會(huì)造成內(nèi)存浪費(fèi)
在使用到的時(shí)候才會(huì)創(chuàng)建對(duì)象。判斷有無(wú)對(duì)象,有則返回,無(wú)創(chuàng)建后再返回
劣勢(shì):只能在單線程下使用,多線程情況下線程不安全 不推薦這種方式的
2.4 懶漢式(線程安全,同步方法)① 在多線程的情況下,有一個(gè)對(duì)象進(jìn)入if判斷通過(guò),還沒(méi)執(zhí)行到創(chuàng)建對(duì)象這一步驟時(shí)
② 有另外一個(gè)對(duì)象也進(jìn)入了if判斷,也通過(guò)了。
此時(shí)就會(huì)出現(xiàn)多個(gè)實(shí)例,造成線程不安全。
在獲取對(duì)象的靜態(tài)方法上添加 synchronized 關(guān)鍵字,實(shí)現(xiàn)同步方法。解決線程不安全問(wèn)題。
代碼案例//加入同步處理 同步方法
class Singleton{//構(gòu)造器私有化
private Singleton(){}
//類的內(nèi)部提供對(duì)象
private static Singleton singleton;
//對(duì)外提供公共的靜態(tài)方法的時(shí)候,來(lái)判斷
public static synchronized Singleton getInstance(){if (singleton == null){singleton = new Singleton();
}
return singleton;
}
}案例分析解決了線程安全問(wèn)題,但是效率太低
2.5 懶漢式(線程不安全,同步代碼塊)每一個(gè)線程需求拿實(shí)例的時(shí)候都要在外面等候另一線程處理完
將實(shí)例化對(duì)象過(guò)程放入同步代碼塊中
代碼案例//加入同步處理 - 同步代碼塊的方式 不推薦的
class Singleton{//構(gòu)造器私有化
private Singleton(){}
//類的內(nèi)部提供對(duì)象
private static Singleton singleton;
//對(duì)外提供公共的靜態(tài)方法的時(shí)候,來(lái)判斷
public static Singleton getInstance(){if (singleton == null){synchronized (Singleton.class){singleton = new Singleton();
}
}
return singleton;
}
}案例分析不推薦的,解決不了線程的安全問(wèn)題
2.6 雙重檢查 (推薦使用) 代碼案例這種方式本意是想解決同步方法的問(wèn)題。但是我們分析一下。在多線程情況下還是有可能創(chuàng)建多個(gè)實(shí)例的問(wèn)題。
class Singleton{private Singleton(){}
//禁止指令重排
private static volatile Singleton singleton;
//加入雙重檢查機(jī)制
public static Singleton getInstance(){if (singleton == null){synchronized (Singleton.class){if (singleton == null){singleton = new Singleton();
}
}
}
return singleton;
}
}案例分析
優(yōu)點(diǎn)線程安全
解決了線程安全問(wèn)題
① 多線程時(shí),若兩個(gè)線程同時(shí)滿足第一層非空判斷,等待調(diào)用同步代碼塊。
② 由于添加了synchronized ,當(dāng)?shù)谝粋€(gè)線程進(jìn)來(lái)時(shí),發(fā)現(xiàn)Singleton對(duì)象為空,進(jìn)行創(chuàng)建對(duì)象并返回。
③ 當(dāng)另外一個(gè)線程調(diào)用同步代碼塊時(shí),進(jìn)行再次對(duì)象非空判斷,發(fā)現(xiàn)對(duì)象已經(jīng)創(chuàng)建成功。不在執(zhí)行創(chuàng)建對(duì)象流程,返回已有對(duì)象
懶加載
使用到對(duì)象時(shí)才創(chuàng)建,不會(huì)造成內(nèi)存的浪費(fèi)
效率很高
可能出現(xiàn)的問(wèn)題先進(jìn)性了singleton 是否為空的判斷,singleton 如果不為空直接返回結(jié)果。倘若無(wú)第一層判空,多線程時(shí)每次都要進(jìn)行synchronized 等待其他線程處理結(jié)束,才能進(jìn)入內(nèi)部非空判斷,效率相對(duì)低。
我們認(rèn)為的 new Singleton() 操作
1)分配內(nèi)存地址 M
2)在內(nèi)存 M 上初始化Singleton 對(duì)象
3)將M的地址賦值給 instance 對(duì)象
JVM編譯優(yōu)化后(指令重排)可能的 new Singleton() 操作
1)分配內(nèi)存地址 M
2)將M的地址賦值給instance變量
3)在內(nèi)存M上初始化 Singleton 對(duì)象
這就有可能出現(xiàn)空指針異常
異常發(fā)生過(guò)程
解決方式:關(guān)鍵字 Volatile 來(lái)禁止指令重排
輕量級(jí)的同步機(jī)制 (低配版) 沒(méi)有保證原子性
三大特性
保證可見(jiàn)性
其中一個(gè)線程修改了主內(nèi)存共享變量的值,要寫回主內(nèi)存,并要及時(shí)通知其他線程可見(jiàn)
沒(méi)有保證原子性
沒(méi)法(不能保證)不可分割,完整,要么同時(shí)成功,要么同時(shí)失敗
禁止指令重排
和底層內(nèi)存屏障相關(guān) 避免多線程下出現(xiàn)指令亂序的情況
擴(kuò)展-線程切換
Java的一條語(yǔ)句對(duì)應(yīng)的cpu指令可能是多條,其中任意一條cpu指令在執(zhí)行完都可能發(fā)生線程切換
count += 1,對(duì)應(yīng)cpu 指令如下:
2.7 靜態(tài)內(nèi)部類 (推薦使用) 代碼案例1)將變量count從內(nèi)存加載到cpu寄存器
2)寄存器中 +1
3)將結(jié)果寫入內(nèi)存(緩存機(jī)制寫入的可能是cpu而不是內(nèi)存)
class Singleton{private Singleton(){}
private static class SingletonInstance{public static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){return SingletonInstance.INSTANCE;
}
}案例分析①當(dāng)Singleton類加載時(shí),靜態(tài)內(nèi)部類是不會(huì)加載的。
②只有調(diào)用getInstance方法用到了SingletonInstance.INSTANCE靜態(tài)變量時(shí)導(dǎo)致SingletonInstance靜態(tài)內(nèi)部類進(jìn)行加載。
不會(huì)出現(xiàn)線程安全問(wèn)題
JVM來(lái)幫我們保證了線程的安全性
利用靜態(tài)內(nèi)部類的特點(diǎn),效率也很高,實(shí)際開(kāi)發(fā)中推薦使用的
public class EnumDemo {public static void main(String[] args) {//驗(yàn)證其正確性
Singleton instance = Singleton.INSTANCE;
Singleton instance1 = Singleton.INSTANCE;
System.out.println(instance == instance1); //true
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
}
}
enum Singleton{INSTANCE; //屬性
}
案例分析不僅可以避免線程安全問(wèn)題 還可以防止反序列化重新創(chuàng)建對(duì)象。推薦使用
三 注意事項(xiàng)你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
文章標(biāo)題:設(shè)計(jì)模式-單例模式(一)-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://www.chinadenli.net/article42/djdeec.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、云服務(wù)器、建站公司、域名注冊(cè)、服務(wù)器托管、企業(yè)網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容