丨單例模式如何創(chuàng)建單一對象優(yōu)化系統(tǒng)性能_第1頁
丨單例模式如何創(chuàng)建單一對象優(yōu)化系統(tǒng)性能_第2頁
丨單例模式如何創(chuàng)建單一對象優(yōu)化系統(tǒng)性能_第3頁
丨單例模式如何創(chuàng)建單一對象優(yōu)化系統(tǒng)性能_第4頁
丨單例模式如何創(chuàng)建單一對象優(yōu)化系統(tǒng)性能_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

結(jié)合這三點,我們來實現(xiàn)一個簡單代碼//餓漢模publicfinalclassSingletonprivatestaticSingletoninstance=newSingleton();//自行創(chuàng)建實privateSingleton(){}//構(gòu)造函publicstaticSingletongetInstance(){//通過該函數(shù)向整個系統(tǒng)提供return 8我們可以發(fā)現(xiàn),以上第一種實現(xiàn)單例的代碼中,使用了static了成員instance,所以該變量會在類初始化的過程中被收集進類構(gòu)造器即<clinit>方法中。在多線程場景下,JVM會保證只有一個線程能執(zhí)行該類的<clinit>方法,其它線程將會被阻塞等待。等到唯一的一次<clinit>方法執(zhí)行完成,其它線程將不會再執(zhí)行<clinit>方法,轉(zhuǎn)而執(zhí)行自己的代碼。也就是說,static修飾了成員變量instance,在多線程的情況下能保證只實餓漢模式實現(xiàn)的單例的優(yōu)點是,可以保證多線程情況下實例的唯一性,而且直接返回唯一實例,性能非情況下,一直占用堆內(nèi)存。試想下,如果一個第開源框架中的類都是基于餓漢模式實的單例,這將會初始化所有單例類,無疑是性的懶漢模式就是為了避免直接加載類對象時提前創(chuàng)建對象的一種單例設計模式。該模式使用懶加載方式,只有當系統(tǒng)使用到類對象時,才會將實例加載到堆內(nèi)存中。通過以下代碼,我們可以簡單地了解下懶加載的實現(xiàn)方式:代碼//懶漢模publicfinalclassSingletonprivatestaticSingletoninstance=null;//不實例privateSingleton(){}//構(gòu)造函publicstaticSingletongetInstance(){//通過該函數(shù)向整個系統(tǒng)提供if(null==instance){//當instance為null時,則實例化對象,否則直接返回instance=newSingleton();//實例化對 returninstance;//返回已存在的 11當線程A入到if斷條件后,開始實例化對象,此時instance然為null;又有線程B進入到if判斷條件中,之后也會通過條件判斷,進入到方法里面創(chuàng)建一個實例對象。所以我們需要對該方法進行加鎖,保證多線程情況下僅創(chuàng)建一個實例。這里我們使Synchronized鎖來修飾getInstance法代碼//懶漢模式+synchronized同步publicfinalclassSingletonprivatestaticSingletoninstance=null;//不實例privateSingleton(){}//構(gòu)造函publicstaticsynchronizedSingletongetInstance(){//加同步鎖,通過該函數(shù)向整個系if(null==instance){//當instance為null時,則實例化對象,否則直接返回instance=newSingleton();//實例化對 returninstance;//返回已存在的 11還有,每次請求獲取類對象時,都會通過getInstance()方法獲取,除了第一次為l它每次請求基本都是不為l的。在沒有加同步鎖之前,是因為f判斷條件為l導致創(chuàng)建了多個實例?;谝陨蟽牲c,我們可以考慮將同步鎖放在f條件里面,這樣就可以減少同步鎖資源競爭。代碼//懶漢模式+synchronized同步publicfinalclassSingletonprivatestaticSingletoninstance=null;//不實例privateSingleton(){}//構(gòu)造函publicstaticSingletongetInstance(){//加同步鎖,通過該函數(shù)向整個系統(tǒng)提供if(null==instance){//當instance為null時,則實例化對象,否則直接返回synchronizedinstance=newSingleton();//實例化對 }returninstance;//返回已存在的 13if判斷條件里,雖然有同步鎖,但是進入到判斷條件里面的線程依然會依次獲取到鎖創(chuàng)建對象,然后再釋放同步鎖。所以我們還需要在同步鎖里面再加一個判斷條件:代碼//懶漢模式+synchronized同步鎖+double-publicfinalclassSingletonprivatestaticSingletoninstance=null;//不實例privateSingleton(){}//構(gòu)造函publicstaticSingletongetInstance(){//加同步鎖,通過該函數(shù)向整個系統(tǒng)提供if(null==instance){//第一次判斷,當instance為null時,則實例化對象,否則直synchronized(Singleton.class){//同步if(null==instance){//第二次判9

instance=newSingleton();//實例化對}returninstance;//返回已存在的}}以上這種方式,通常被稱為Double-Check,它可以大大提高支持多線程的懶漢模式的運其實這里又跟Happens-Before規(guī)則和重排序扯上關系了,這里我們先來簡單了解Happens-Before規(guī)則和重排序我們在第二期餐中過譯器盡可減少器的、數(shù),分復用寄存器的值,比如以下代碼,如果沒有進行重排序優(yōu)化,正常的執(zhí)行順序是步驟\\,而在編譯期間進行了重排序優(yōu)化之后,執(zhí)行的步驟有可能就變成了步驟/2樣就能減少一次寄存器的存取次數(shù)。代碼inta=1;//步驟1:加載a變量的內(nèi)存地址到寄存器中,加載1到寄存器中,CPU通過mov指令intb=2;//步驟2加載b變量的內(nèi)存地址到寄存器中,加載2到寄存器中,CPU通過mov指令把a=a+1;//步驟3重新加載a變量的內(nèi)存地址到寄存器中,加載1到寄存器中,CPU通過mov在JMM中,重排序是十分重要的一環(huán),特別是在并發(fā)編程中。如果JVM任意排序以提高程序性能,也可能會給并發(fā)編程帶來一系列的問題。例如,我上面講到的oub-Check的單例問題,假設類中有其它的屬性也需要實例化,這個時候,除了要實例化單例類本身,還需要對其它屬性也進行實例化:代碼//懶漢模式+synchronized同步鎖+double-publicfinalclassSingletonprivatestaticSingletoninstance=null;//不實例publicList<String>list=null;//list屬privatelist=new}//構(gòu)造函8918

publicstaticSingletongetInstance(){//加同步鎖,通過該函數(shù)向整個系統(tǒng)提供if(null==instance){//第一次判斷,當instance為null時,則實例化對象,否則直synchronized(Singleton.class){//同步if(null==instance){//第二次判instance=newSingleton();//實例化對}}}returninstance;//返回已存在的}在執(zhí)行instance=newSingleton();代碼時,正常情況下,實例過程這樣給Singleton分配內(nèi)存調(diào)用Singleton的構(gòu)造函數(shù)來初始化成員變將Singleton對象指向分配的內(nèi)存空間(執(zhí)行完這步singleton就為非null了)如果虛擬機發(fā)生了重排序優(yōu)化,這個時候步驟3可能發(fā)生在步驟2之前。如果初始化線程剛好完成步驟3,而步驟2沒有進行時,則剛好有另一個線程到了第一次判斷,這個時候判斷為非null,并返回對象使用,這個時候?qū)嶋H沒有完成其它屬性的構(gòu)造,因此使用這個屬性就很可能會導致異常。在這里,Synchronized只能保證可見性、原子性,無法保證執(zhí)這個時候,就體現(xiàn)出Happens-Before規(guī)則的重要性了。通過字面意思,你可能會誤以為我們知道volatile關鍵字可以保證線程間變量的可見性,簡單地說就是當線程A對變量X進行修改后,程A后面執(zhí)行的其它線程就能看到變量X的變動。除此之外,volatile在JDK1.5之后還有一個作用就是局部重排序的發(fā)生,也就是說,volatile變量的操作指令都不會被重排序。所以使用volatile修飾instance之后,Double-Check懶漢單例模代碼//懶漢模式+synchronized同步鎖+double-publicfinalclassSingletonprivatevolatilestaticSingletoninstance=null;//不實例publicList<String>list=null;//list屬private6list=new7}//構(gòu)造函8publicstaticSingletongetInstance(){//加同步鎖,通過該函數(shù)向整個系統(tǒng)提供9if(null==instance){//第一次判斷,當instance為null時,則實例化對象,否則直synchronized(Singleton.class){//同步if(null==instance){//第二次判instance=newSingleton();//實例化對}}}returninstance;//返回已存在的}}以上這種同步鎖+Double-Check實現(xiàn)方式相對來說,復雜且加了同步鎖,那有沒有稍我們知道,在餓漢模式中,我們使用了static修飾了成員變量instance,所以該變量會在類初始化的過程中被收集進類構(gòu)造器即<clinit>方法中。在多線程場景下,JVM會保證只有一個線程能執(zhí)行該類的<clinit>方法,其它線程將會被阻塞等待。這種方式可以保證內(nèi)如果我們在Singleton類中創(chuàng)建一個內(nèi)部類來實現(xiàn)成員變量的初始化,則可以避免多線程下重復創(chuàng)建對象的情況發(fā)生。這種方式,只有在第一次調(diào)用getInstance()方法時,才會加載InnerSingleton類,而只有在加載InnerSingleton類之后,才會實例化創(chuàng)建對象。具代碼//懶漢模式內(nèi)部類實publicfinalclassSingletonpublicList<String>list=null;//list屬4privateSingleton(){//構(gòu)造函list=new 8 //內(nèi)部類17

publicstaticclassInnerSingletonprivatestaticSingletoninstance=newSingleton();//自行創(chuàng)建實}publicstaticSingletongetInstance()returnInnerSingleton.instance;//返回內(nèi)部類中的靜態(tài)變}如果我們在程序啟動后,一定會加載到類,那么用餓漢模式實現(xiàn)的單例簡單又實用;如果我們是寫一些工具類,則優(yōu)先考慮使用懶漢模式,因為很多項目可能會到r,但未除了以上那些實現(xiàn)單例的方式,你還知道其它實現(xiàn)方 科技所有 不 售賣。頁面已增加防盜追蹤,將依 上一 25|答疑課堂:模塊四熱點問題解下一 27|原型模式與享元模式:提升系統(tǒng)性能的利精選留言展9使用枚舉來實現(xiàn)單例模式,具體代碼如下:publicclass{privatestaticSinletonExample5instance=private展7相比DoubleCheck,以內(nèi)部類方式實現(xiàn)單例模式,代碼簡潔,性能相近,在我看來是更優(yōu)展3展3方式和枚

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論