單例設(shè)計(jì)模式(Singleton Pattern)是最簡(jiǎn)單且常見(jiàn)的設(shè)計(jì)模式之一猿挚,主要作用是提供一個(gè)全局訪問(wèn)且只實(shí)例化一次的對(duì)象咐旧,避免多實(shí)例對(duì)象的情況下引起邏輯性錯(cuò)誤(實(shí)例化數(shù)量可控)…
概述
Java中,單例模式主要分三種:懶漢式單例绩蜻、餓漢式單例铣墨、登記式單例三種。
特點(diǎn)
案例
在這里我推薦下我自己的JAVAqun:479121291办绝,不管你是小白還是大牛伊约,小編我都挺歡迎,不定期分享干貨孕蝉,包括我自己整理的一份最新JAVA資料和零基礎(chǔ)入門(mén)教程碱妆!,歡迎初學(xué)和進(jìn)階中的小伙伴昔驱。
注意事項(xiàng)
解鎖姿勢(shì)
第一種:?jiǎn)我粰z查(懶漢)非線程安全
日志
分析: 在單線程環(huán)境一切正常,balancer1和balancer2兩個(gè)對(duì)象的hashCode一模一樣上忍,由此可以判斷出堆棧中只有一份內(nèi)容骤肛,不過(guò)該代碼塊中存在線程安全隱患,因?yàn)槿狈Ω?jìng)爭(zhēng)條件窍蓝,多線程環(huán)境資源競(jìng)爭(zhēng)的時(shí)候就顯得不太樂(lè)觀了腋颠,請(qǐng)看上文代碼注釋內(nèi)容
第二種:無(wú)腦上鎖(懶漢)線程安全,性能較差吓笙,第一種升級(jí)版
分析: 毫無(wú)疑問(wèn)淑玫,知道synchronized關(guān)鍵字的都知道,同步方法在鎖沒(méi)釋放之前,其它線程都在排隊(duì)候著呢絮蒿,想不安全都不行啊尊搬,但在安全的同時(shí),性能方面就顯得短板了土涝,我就初始化一次佛寿,你丫的每次來(lái)都上個(gè)鎖,不累的嗎(沒(méi)關(guān)系但壮,它是為了第三種做鋪墊的)..
第三種:雙重檢查鎖(DCL)冀泻,完全就是前兩種的結(jié)合體啊,有木有蜡饵,只是將同步方法升級(jí)成了同步代碼塊
1.假設(shè)new LazyLoadBalancer()加載內(nèi)容過(guò)多
2.因重排而導(dǎo)致loadBalancer提前不為空
3.正好被其它線程觀察到對(duì)象非空直接返回使用
存在問(wèn)題: 首先我們一定要清楚弹渔,DCL是不能保證線程安全的,稍微了解過(guò)JVM的就清楚溯祸,對(duì)比C/C++它始終缺少一個(gè)正式的內(nèi)存模型肢专,所以為了提升性能,它還會(huì)做一次指令重排操作您没,這個(gè)時(shí)候就會(huì)導(dǎo)致loadBalancer提前不為空鸟召,正好被其它線程觀察到對(duì)象非空直接返回使用(但實(shí)際還有部分內(nèi)容沒(méi)加載完成)
解決方案: 用volatile修飾loadBalancer,因?yàn)関olatile修飾的成員變量可以確保多個(gè)線程都能夠順序處理氨鹏,它會(huì)屏蔽JVM指令重排帶來(lái)的性能優(yōu)化欧募。
第四種:Demand Holder (懶漢)線程安全,推薦使用
分析: 在Demand Holder中仆抵,我們?cè)贚azyLoadBalancer里增加一個(gè)靜態(tài)(static)內(nèi)部類跟继,在該內(nèi)部類中創(chuàng)建單例對(duì)象,再將該單例對(duì)象通過(guò)getInstance()方法返回給外部使用镣丑,由于靜態(tài)單例對(duì)象沒(méi)有作為L(zhǎng)azyLoadBalancer的成員變量直接實(shí)例化舔糖,類加載時(shí)并不會(huì)實(shí)例化LoadBalancerHolder,因此既可以實(shí)現(xiàn)延遲加載莺匠,又可以保證線程安全金吗,不影響系統(tǒng)性能(居家旅行必備良藥啊)
第五種:枚舉特性(懶漢)線程安全趣竣,推薦使用
分析: 相比上一種摇庙,該方式同樣是用到了JAVA特性:枚舉類保證只有一個(gè)實(shí)例(即使使用反射機(jī)制也無(wú)法多次實(shí)例化一個(gè)枚舉量)
第六種:餓漢單例(天生線程安全),
分析: 利用ClassLoad機(jī)制遥缕,在加載時(shí)進(jìn)行實(shí)例化卫袒,同時(shí)靜態(tài)方法只在編譯期間執(zhí)行一次初始化,也就只有一個(gè)對(duì)象单匣。使用的時(shí)候已被初始化完畢可以直接調(diào)用夕凝,但是相比懶漢模式宝穗,它在使用的時(shí)候速度最快,但這玩意就像自己挖的坑哭著也得跳码秉,你不用也得初始化一份在內(nèi)存中占個(gè)坑…