版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第一文帶你搞懂Java單例模式目錄一、單例模式的基本寫法二、單例模式的作用三、單例模式的變種1.餓漢式2.懶漢式(線程不安全)3.懶漢式(線程安全)4.雙檢鎖/雙重校驗鎖(DCL,double-checkedlocking)5.靜態(tài)內(nèi)部類6.枚舉7.登記式8.Spring容器在創(chuàng)建型設(shè)計模式中,我們第一個學(xué)習(xí)的是單例模式(SingletonPattern),這是設(shè)計模式中最簡單的模式之一。
單例是什么意思呢?
單例就是單實例的意思,即在系統(tǒng)全局,一個類只創(chuàng)建一個對象,并且在系統(tǒng)全局都可以訪問這個對象而不用重新創(chuàng)建。
一、單例模式的基本寫法
單例模式示例代碼:
publicclassSingleton{
//Singleton類自己持有這個單例對象
privatestaticSingletoninstance=newSingleton();
//構(gòu)造方法設(shè)置為私有,避免在Singleton類外部創(chuàng)建Singleton對象
privateSingleton(){}
//提供獲取單例對象的靜態(tài)方法
publicstaticSingletongetInstance(){
returninstance;
publicvoidhello(){
System.out.println("Hello!");
}
使用:
Singletonobj=Singleton.getInstance();
obj.hello();
分析SingleObject類的特征:
SingleObject類的構(gòu)造方法是私有的,這樣可以保證只能在SingleObject類內(nèi)部才能創(chuàng)建對象,而無法在類外部創(chuàng)建SingleObject對象。SingleObject類中有一個instance成員屬性,它用來持有這個SingleObject對象。SingleObject類提供了一個靜態(tài)方法getInstance,它可以讓我們在任何可以訪問到SingleObject類的地方,都可以使用SingleObject.getInstance()來獲取到這個SingleObject對象。
二、單例模式的作用
單例模式有什么用呢?
1.控制對象的數(shù)量
當(dāng)你編寫了一個類提供給其他人調(diào)用時,對方看到是一個類,很有可能第一反應(yīng)是嘗試new一下。
你自己編寫的類你自己是清楚如何使用的,在整個系統(tǒng)內(nèi)這個類只需要創(chuàng)建一個對象就夠了,但對方可能并不清楚。
這時候你可以把這個類編寫為單例形式,把構(gòu)造方法私有化,讓對方無法通過new來創(chuàng)建對象,只能使用getInstance來獲取。
這個模式可以幫助你有效的控制對象的數(shù)量,畢竟,有的類其內(nèi)部實現(xiàn)復(fù)雜,如果頻繁創(chuàng)建銷毀對象,可能還是很耗費(fèi)服務(wù)器資源的。
2.全局訪問
單例模式的特點是單例類自己持有這個單例對象,并且提供一個靜態(tài)方法可在全局獲取到這個單例對象。
如果沒有單例模式的情況下,我們一般是在代碼A處創(chuàng)建這個對象,在代碼B處如果也要使用這個對象,就需要將這個對象進(jìn)行參數(shù)傳遞。為了避免傳來傳去,我們可能會寫個Holder類,把這個對象放在Holder的成員變量中。
而單例模式的這個優(yōu)點是,我們可以避免這樣的困擾,直接從單例類中獲取。
三、單例模式的變種
上面介紹的是單例模式的一種基本寫法,實際我們還可以對其進(jìn)行優(yōu)化和變種。
1.餓漢式
基本寫法中,對象的創(chuàng)建是直接寫在Singleton類的成員屬性上的,因此當(dāng)Singleton類被加載時,就會立即創(chuàng)建Singleton對象,這個寫法比較簡單,但我們可能并不會馬上使用到這個Singleton對象,過早的創(chuàng)建會造成內(nèi)存資源浪費(fèi)。
這種一加載類就急于創(chuàng)建對象的寫法,我們稱之為餓漢式。
如果對內(nèi)存資源不在意,那么其實餓漢式這個寫法也就沒什么大的缺點,而且寫起來還簡單,還是可以用的。
2.懶漢式(線程不安全)
此變種僅是介紹,不要使用。
既然餓漢式在類加載時就創(chuàng)建對象會造成內(nèi)存浪費(fèi),那么我們把創(chuàng)建對象這個步驟挪到要用時再創(chuàng)建不就好了?
我們要使用對象時,都是通過getInstance方法先獲取對象,我們可以在getInstance方法中完成對象創(chuàng)建。
這種需要時再創(chuàng)建的寫法,我們稱之為懶漢式
示例代碼:
publicclassSingleton{
privatestaticSingletoninstance;
privateSingleton(){}
publicstaticSingletongetInstance(){
if(instance==null){
instance=newSingleton();
returninstance;
}
分析懶漢式(線程不安全)寫法的特點:
創(chuàng)建對象的時機(jī)修改為了在getInstance內(nèi)部,需要時再創(chuàng)建,這可以節(jié)約系統(tǒng)資源getInstance方法在多個線程并發(fā)調(diào)用時,有可能會出現(xiàn)創(chuàng)建了多個實例,所以這算是一個不好的單例變種示范
餓漢式?jīng)]有多線程并發(fā)問題嗎?
確實沒有,因為餓漢式是在類加載時進(jìn)行創(chuàng)建對象,類加載classloader是單線程的,不存在這個問題。
3.懶漢式(線程安全)
此變種僅是介紹,不要使用。
懶漢式(線程不安全)有可能存在并發(fā)問題,導(dǎo)致創(chuàng)建多個實例,那么我們給他加上鎖不就好了嗎?
示例代碼:
publicclassSingleton{
privatestaticSingletoninstance;
privateSingleton(){}
publicstaticsynchronizedSingletongetInstance(){
if(instance==null){
instance=newSingleton();
returninstance;
}
分析懶漢式寫法的特點:
由于調(diào)用getInstance時如果instance為null會創(chuàng)建對象,如果多個線程同時調(diào)用getInstance方法,有可能出現(xiàn)同步問題導(dǎo)致創(chuàng)建多個實例,所以getInstance方法使用了synchronized加鎖來保障并發(fā)情況下也只會創(chuàng)建一個實例,不過synchronized的粒度較大,如果每次請求都經(jīng)過getInstance方法,性能影響較大。
4.雙檢鎖/雙重校驗鎖(DCL,double-checkedlocking)
懶漢式(線程安全)已經(jīng)可以達(dá)到節(jié)省資源的目的,也達(dá)到了線程安全的目的,但是使用synchronized加鎖對性能有較大影響,雙檢鎖的方式,則是把鎖的粒度盡可能降低,減少加鎖對性能的影響。
示例代碼:
publicclassSingleton{
privatevolatilestaticSingletoninstance;
privateSingleton(){}
publicstaticSingletongetSingleton(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=newSingleton();
returnsingleton;
}
分析雙檢鎖的寫法:
在成員屬性instance上,我們增加了volatile關(guān)鍵字,保障多線程對instance值的可見性以及禁止指令重排。通過雙重檢查的方式,在內(nèi)部再進(jìn)行synchronized加鎖,可以降低鎖的粒度,有效避免每次調(diào)用getInstance都加鎖,因為getInstance在創(chuàng)建對象之后,instance一直都是非null的。
雙檢鎖這個方式,既可以保障不浪費(fèi)資源,又可以保障在多線程的環(huán)境下保持高性能。
如果大家自行編寫單例類,追求節(jié)約資源和高性能,可以使用這種寫法,但據(jù)《Java并發(fā)編程實踐》提到不贊成這個寫法,推薦靜態(tài)內(nèi)部類的方式(這一點我尚未驗證)。
5.靜態(tài)內(nèi)部類
這個變種,可以達(dá)到和雙檢鎖一樣的效果,并且寫起來更加簡單,推薦使用。
publicclassSingleton{
privatestaticclassSingletonHolder{
privatestaticfinalSingletonINSTANCE=newSingleton();
privateSingleton(){}
publicstaticfinalSingletongetInstance(){
returnSingletonHolder.INSTANCE;
}
分析一下靜態(tài)內(nèi)部類的特點:
將instance放在了內(nèi)部類SingletonHolder中,前面我們提到餓漢式是類加載時就會立即創(chuàng)建對象,而靜態(tài)內(nèi)部類不會,它只會在調(diào)用了getInstance時,才會加載內(nèi)部類SingletonHolder,此時才會創(chuàng)建對象。
6.枚舉
這個方式,這里僅是從網(wǎng)上摘抄,據(jù)說是很好,但是沒有試過,工作中也很少見。
這種實現(xiàn)方式還沒有被廣泛采用,但這是實現(xiàn)單例模式的最佳方法。
它更簡潔,自動支持序列化機(jī)制,絕對防止多次實例化。
這種方式是EffectiveJava作者JoshBloch提倡的方式,它不僅能避免多線程同步問題,而且還自動支持序列化機(jī)制,防止反序列化重新創(chuàng)建新的對象,絕對防止多次實例化。
不過,由于JDK1.5之后才加入enum特性,用這種方式寫不免讓人感覺生疏,在實際工作中,也很少用。
不能通過reflectionattack來調(diào)用私有構(gòu)造方法。
publicenumSingleton{
INSTANCE;
publicvoidwhateverMethod(){
}
7.登記式
如果熟悉我們封裝的工具包Toolbox,就會知道工具包內(nèi)提供了一個登記式單例工具類Singleton。
單例模式是一種非常常用的設(shè)計模式,但以上介紹的各種方法,都需要為每個單例類編寫一些模板式的代碼,為了簡化,我們可以使用Singleton工具類。
//獲取單例對象
//Student類必須要具備無參構(gòu)造方法
//每個類在一個進(jìn)程中只能獲得一個單例對象
Studentstudent=Singleton.get(Student.class);
//移除單例對象
Singleton.remove(Student.class);
//清空所有單例對象
Singleton.clear();
//單例對象數(shù)量
intsize=Singleton.size();
其實他就是很像是spring容器。
Singleton.java:
/**
*單例工具
*@authorUnicorn
publicfinalclassSingleton{
*對象池
privatestaticMapString,Objectpool=newConcurrentHashMap();
privateSingleton(){}
publicstaticTTget(ClassTclazz){
Assert.notNull(clazz);
Stringkey=clazz.getName();
Tobj=(T)pool.get(key);
if(null==obj){
synchronized(Singleton.class){
obj=(T)pool.get(key);
if(null==obj){
obj=ReflectUtil.newInstance(clazz);
pool.put(key,obj);
returnobj;
*移除對象
*@paramclazz
publicsta
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年公務(wù)員面試寶典公共管理與政策理解題集
- 2026年常州紡織服裝職業(yè)技術(shù)學(xué)院單招職業(yè)傾向性測試題庫附答案解析
- 保衛(wèi)施工技術(shù)方案
- 2024年硯山縣招教考試備考題庫帶答案解析
- 2025年廣西安全工程職業(yè)技術(shù)學(xué)院單招職業(yè)適應(yīng)性測試題庫帶答案解析
- 2026年安徽冶金科技職業(yè)學(xué)院單招職業(yè)適應(yīng)性測試題庫帶答案解析
- 2024年石家莊郵電職業(yè)技術(shù)學(xué)院馬克思主義基本原理概論期末考試題及答案解析(必刷)
- 2025年嘉興南洋職業(yè)技術(shù)學(xué)院馬克思主義基本原理概論期末考試模擬題附答案解析(必刷)
- 2025年江西科技職業(yè)學(xué)院單招職業(yè)適應(yīng)性考試題庫帶答案解析
- 2025年新鄉(xiāng)縣幼兒園教師招教考試備考題庫及答案解析(奪冠)
- 研學(xué)旅行概論 課件 第六章 研學(xué)旅行專業(yè)人員
- 員 工 調(diào) 動 申 請 表
- 工裝治具設(shè)計規(guī)范
- 手衛(wèi)生知識培訓(xùn)內(nèi)容(通用3篇)
- 無損檢測質(zhì)量記錄表格
- 膠配膠車間安全操作規(guī)程
- 美國AAMA檢驗標(biāo)準(zhǔn)
- 2023牛津譯林版本9Aunit1詞匯表(詞性漢語)
- 高速公路機(jī)電消防施工組織設(shè)計
- GB/T 24135-2022橡膠或塑料涂覆織物加速老化試驗
- CO2汽提尿素自控授課
評論
0/150
提交評論