日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

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

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

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


一、懶漢式單例

[java]?view plain?copy ?print? //懶漢式單例類.在第一次調(diào)用的時(shí)候?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避免了類在外部被實(shí)例化,在同一個(gè)虛擬機(jī)范圍內(nèi),Singleton的唯一實(shí)例只能通過getInstance()方法訪問。

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

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


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都好一些,既實(shí)現(xiàn)了線程安全,又避免了同步帶來的性能影響。


二、餓漢式單例

[java]?view plain?copy ?print? //餓漢式單例類.在類初始化時(shí),已經(jīng)自行實(shí)例化??? public?class?Singleton1?{?? ????private?Singleton1()?{}?? ????private?static?final?Singleton1?single?=?new?Singleton1();?? ????//靜態(tài)工廠方法??? ????public?static?Singleton1?getInstance()?{?? ????????return?single;?? ????}?? }?? 餓漢式在類創(chuàng)建的同時(shí)就已經(jīng)創(chuàng)建好一個(gè)靜態(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);?? ????}?? ????//保護(hù)的默認(rèn)構(gòu)造子?? ????protected?Singleton3(){}?? ????//靜態(tài)工廠方法,返還此類惟一的實(shí)例?? ????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);?? ????}?? ????//一個(gè)示意性的商業(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());?? ????}?? }??

?登記式單例實(shí)際上維護(hù)了一組單例類的實(shí)例,將這些實(shí)例存放在一個(gè)Map(登記?。┲校瑢τ谝呀?jīng)登記過的實(shí)例,則從Map直接返回,對于沒有登記的,則先登記,然后返回。?

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


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

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

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

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

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


1、線程安全:

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

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



2、資源加載和性能:

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

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

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

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

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

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


什么是線程安全?

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

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


應(yīng)用

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

[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)建的是同一個(gè)實(shí)例");?? ????????}else{?? ????????????System.out.println("創(chuàng)建的不是同一個(gè)實(shí)例");?? ????????}?? ????}?? }??

?運(yùn)行結(jié)果:


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

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



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


作者:jason0539

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




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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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