www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > > 充電吧
[導(dǎo)讀] 本文繼續(xù)介紹23種設(shè)計模式系列之單例模式。 概念:  Java中單例模式是一種常見的設(shè)計模式,單例模式的寫法有好幾種,這里主要介紹三種:懶漢式單例、餓漢式單例、登記式單例?! 卫J接幸韵绿攸c

本文繼續(xù)介紹23種設(shè)計模式系列之單例模式。

概念:
  Java中單例模式是一種常見的設(shè)計模式,單例模式的寫法有好幾種,這里主要介紹三種:懶漢式單例、餓漢式單例、登記式單例。
  單例模式有以下特點:
  1、單例類只能有一個實例。
  2、單例類必須自己創(chuàng)建自己的唯一實例。
  3、單例類必須給所有其他對象提供這一實例。
  單例模式確保某個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例。在計算機系統(tǒng)中,線程池、緩存、日志對象、對話框、打印機、顯卡的驅(qū)動程序?qū)ο蟪1辉O(shè)計成單例。這些應(yīng)用都或多或少具有資源管理器的功能。每臺計算機可以有若干個打印機,但只能有一個Printer Spooler,以避免兩個打印作業(yè)同時輸出到打印機中。每臺計算機可以有若干通信端口,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調(diào)用??傊x擇單例模式就是為了避免不一致狀態(tài),避免政出多頭。


一、懶漢式單例

[java]?view plain?copy ?print? //懶漢式單例類.在第一次調(diào)用的時候?qū)嵗约??? public?class?Singleton?{?? ????private?Singleton()?{}?? ????private?static?Singleton?single=null;?? ????//靜態(tài)工廠方法??? ????public?static?Singleton?getInstance()?{?? ?????????if?(single?==?null)?{???? ?????????????single?=?new?Singleton();?? ?????????}???? ????????return?single;?? ????}?? }??
Singleton通過將構(gòu)造方法限定為private避免了類在外部被實例化,在同一個虛擬機范圍內(nèi),Singleton的唯一實例只能通過getInstance()方法訪問。

(事實上,通過Java反射機制是能夠?qū)嵗瘶?gòu)造方法為private的類的,那基本上會使所有的Java單例實現(xiàn)失效。此問題在此處不做討論,姑且掩耳盜鈴地認為反射機制不存在。)

但是以上懶漢式單例的實現(xiàn)沒有考慮線程安全問題,它是線程不安全的,并發(fā)環(huán)境下很可能出現(xiàn)多個Singleton實例,要實現(xiàn)線程安全,有以下三種方式,都是對getInstance這個方法改造,保證了懶漢式單例的線程安全,如果你第一次接觸單例模式,對線程安全不是很了解,可以先跳過下面這三小條,去看餓漢式單例,等看完后面再回頭考慮線程安全的問題:


1、在getInstance方法上加同步

[java]?view plain?copy ?print? public?static?synchronized?Singleton?getInstance()?{?? ?????????if?(single?==?null)?{???? ?????????????single?=?new?Singleton();?? ?????????}???? ????????return?single;?? }??

2、雙重檢查鎖定

[java]?view plain?copy ?print? public?static?Singleton?getInstance()?{?? ????????if?(singleton?==?null)?{???? ????????????synchronized?(Singleton.class)?{???? ???????????????if?(singleton?==?null)?{???? ??????????????????singleton?=?new?Singleton();??? ???????????????}???? ????????????}???? ????????}???? ????????return?singleton;??? ????}??

3、靜態(tài)內(nèi)部類

[java]?view plain?copy ?print? public?class?Singleton?{???? ????private?static?class?LazyHolder?{???? ???????private?static?final?Singleton?INSTANCE?=?new?Singleton();???? ????}???? ????private?Singleton?(){}???? ????public?static?final?Singleton?getInstance()?{???? ???????return?LazyHolder.INSTANCE;???? ????}???? }???? 這種比上面1、2都好一些,既實現(xiàn)了線程安全,又避免了同步帶來的性能影響。


二、餓漢式單例

[java]?view plain?copy ?print? //餓漢式單例類.在類初始化時,已經(jīng)自行實例化??? public?class?Singleton1?{?? ????private?Singleton1()?{}?? ????private?static?final?Singleton1?single?=?new?Singleton1();?? ????//靜態(tài)工廠方法??? ????public?static?Singleton1?getInstance()?{?? ????????return?single;?? ????}?? }?? 餓漢式在類創(chuàng)建的同時就已經(jīng)創(chuàng)建好一個靜態(tài)的對象供系統(tǒng)使用,以后不再改變,所以天生是線程安全的。

三、登記式單例(可忽略)

[java]?view plain?copy ?print? //類似Spring里面的方法,將類名注冊,下次從里面直接獲取。?? public?class?Singleton3?{?? ????private?static?Map?map?=?new?HashMap();?? ????static{?? ????????Singleton3?single?=?new?Singleton3();?? ????????map.put(single.getClass().getName(),?single);?? ????}?? ????//保護的默認構(gòu)造子?? ????protected?Singleton3(){}?? ????//靜態(tài)工廠方法,返還此類惟一的實例?? ????public?static?Singleton3?getInstance(String?name)?{?? ????????if(name?==?null)?{?? ????????????name?=?Singleton3.class.getName();?? ????????????System.out.println("name?==?null"+"--->name="+name);?? ????????}?? ????????if(map.get(name)?==?null)?{?? ????????????try?{?? ????????????????map.put(name,?(Singleton3)?Class.forName(name).newInstance());?? ????????????}?catch?(InstantiationException?e)?{?? ????????????????e.printStackTrace();?? ????????????}?catch?(IllegalAccessException?e)?{?? ????????????????e.printStackTrace();?? ????????????}?catch?(ClassNotFoundException?e)?{?? ????????????????e.printStackTrace();?? ????????????}?? ????????}?? ????????return?map.get(name);?? ????}?? ????//一個示意性的商業(yè)方法?? ????public?String?about()?{?????? ????????return?"Hello,?I?am?RegSingleton.";?????? ????}?????? ????public?static?void?main(String[]?args)?{?? ????????Singleton3?single3?=?Singleton3.getInstance(null);?? ????????System.out.println(single3.about());?? ????}?? }??

?登記式單例實際上維護了一組單例類的實例,將這些實例存放在一個Map(登記?。┲?,對于已經(jīng)登記過的實例,則從Map直接返回,對于沒有登記的,則先登記,然后返回。?

這里我對登記式單例標(biāo)記了可忽略,我的理解來說,首先它用的比較少,另外其實內(nèi)部實現(xiàn)還是用的餓漢式單例,因為其中的static方法塊,它的單例在類被裝載的時候就被實例化了。


餓漢式和懶漢式區(qū)別

從名字上來說,餓漢和懶漢,

餓漢就是類一旦加載,就把單例初始化完成,保證getInstance的時候,單例是已經(jīng)存在的了,

而懶漢比較懶,只有當(dāng)調(diào)用getInstance的時候,才回去初始化這個單例。

另外從以下兩點再區(qū)分以下這兩種方式:


1、線程安全:

餓漢式天生就是線程安全的,可以直接用于多線程而不會出現(xiàn)問題,

懶漢式本身是非線程安全的,為了實現(xiàn)線程安全有幾種寫法,分別是上面的1、2、3,這三種實現(xiàn)在資源加載和性能方面有些區(qū)別。



2、資源加載和性能:

餓漢式在類創(chuàng)建的同時就實例化一個靜態(tài)對象出來,不管之后會不會使用這個單例,都會占據(jù)一定的內(nèi)存,但是相應(yīng)的,在第一次調(diào)用時速度也會更快,因為其資源已經(jīng)初始化完成,

而懶漢式顧名思義,會延遲加載,在第一次使用該單例的時候才會實例化對象出來,第一次調(diào)用時要做初始化,如果要做的工作比較多,性能上會有些延遲,之后就和餓漢式一樣了。

至于1、2、3這三種實現(xiàn)又有些區(qū)別,

第1種,在方法調(diào)用上加了同步,雖然線程安全了,但是每次都要同步,會影響性能,畢竟99%的情況下是不需要同步的,

第2種,在getInstance中做了兩次null檢查,確保了只有第一次調(diào)用單例的時候才會做同步,這樣也是線程安全的,同時避免了每次都同步的性能損耗

第3種,利用了classloader的機制來保證初始化instance時只有一個線程,所以也是線程安全的,同時沒有性能損耗,所以一般我傾向于使用這一種。


什么是線程安全?

如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結(jié)果和單線程運行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的。

或者說:一個類或者程序所提供的接口對于線程來說是原子操作,或者多個線程之間的切換不會導(dǎo)致該接口的執(zhí)行結(jié)果存在二義性,也就是說我們不用考慮同步的問題,那就是線程安全的。


應(yīng)用

以下是一個單例類使用的例子,以懶漢式為例,這里為了保證線程安全,使用了雙重檢查鎖定的方式:

[java]?view plain?copy ?print? public?class?TestSingleton?{?? ????String?name?=?null;?? ?? ????????private?TestSingleton()?{?? ????}?? ?? ????private?static?volatile?TestSingleton?instance?=?null;?? ?? ????public?static?TestSingleton?getInstance()?{?? ???????????if?(instance?==?null)?{???? ?????????????synchronized?(TestSingleton.class)?{???? ????????????????if?(instance?==?null)?{???? ???????????????????instance?=?new?TestSingleton();??? ????????????????}???? ?????????????}???? ???????????}??? ???????????return?instance;?? ????}?? ?? ????public?String?getName()?{?? ????????return?name;?? ????}?? ?? ????public?void?setName(String?name)?{?? ????????this.name?=?name;?? ????}?? ?? ????public?void?printInfo()?{?? ????????System.out.println("the?name?is?"?+?name);?? ????}?? ?? }??

可以看到里面加了volatile關(guān)鍵字來聲明單例對象,既然synchronized已經(jīng)起到了多線程下原子性、有序性、可見性的作用,為什么還要加volatile呢,原因已經(jīng)在下面評論中提到,

還有疑問可參考http://www.iteye.com/topic/652440
和http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html


[java]?view plain?copy ?print? public?class?TMain?{?? ????public?static?void?main(String[]?args){?? ????????TestStream?ts1?=?TestSingleton.getInstance();?? ????????ts1.setName("jason");?? ????????TestStream?ts2?=?TestSingleton.getInstance();?? ????????ts2.setName("0539");?? ?????????? ????????ts1.printInfo();?? ????????ts2.printInfo();?? ?????????? ????????if(ts1?==?ts2){?? ????????????System.out.println("創(chuàng)建的是同一個實例");?? ????????}else{?? ????????????System.out.println("創(chuàng)建的不是同一個實例");?? ????????}?? ????}?? }??

?運行結(jié)果:


結(jié)論:由結(jié)果可以得知單例模式為一個面向?qū)ο蟮膽?yīng)用程序提供了對象惟一的訪問點,不管它實現(xiàn)何種功能,整個應(yīng)用程序都會同享一個實例對象。

對于單例模式的幾種實現(xiàn)方式,知道餓漢式和懶漢式的區(qū)別,線程安全,資源加載的時機,還有懶漢式為了實現(xiàn)線程安全的3種方式的細微差別。



更多設(shè)計模式:23種設(shè)計模式系列


作者:jason0539

博客:http://blog.csdn.net/jason0539(轉(zhuǎn)載請說明出處)




本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉