定義:在《設(shè)計(jì)模式》一書(shū)中,作者這樣來(lái)敘述單例模式的:確保一個(gè)類只有一個(gè)實(shí)例并提供一個(gè)對(duì)它的全局訪問(wèn)指針。單例模式適合于一個(gè)類只有一個(gè)實(shí)例的情況,,比如窗口管理器,,打印緩沖池和文件系統(tǒng),它們都是原型的例子,。典型的情況是,,那些對(duì)象的類型被遍及一個(gè)軟件系統(tǒng)的不同對(duì)象訪問(wèn),因此需要一個(gè)全局的訪問(wèn)指針,,這便是眾所周知的單例模式的應(yīng)用,。當(dāng)然這只有在你確信你不再需要任何多于一個(gè)的實(shí)例的情況下。 單例模式看起來(lái)是最簡(jiǎn)單的設(shè)計(jì)模式之一,,但是使用不當(dāng)?shù)脑?,?huì)存在很多的缺陷。 經(jīng)典的單例模式如下:
將ClassicSingleton類聲明為final的,,確保類不能被隨意實(shí)例化,,另一種可行的方案是把構(gòu)造函數(shù)聲明為private,保證不能被客戶端實(shí)例化,,但是不可以聲明為protected的,,因?yàn)槿绻衅渌悓?duì)其進(jìn)行了繼承,則仍可對(duì)其進(jìn)行實(shí)例化,,創(chuàng)建新的對(duì)象,。 下面引用David Geary的一段話: 關(guān)于ClassicSingleton的感興趣的地方是,如果單例由不同的類裝載器裝入,,那便有可能存在多個(gè)單例類的實(shí)例,。假定不是遠(yuǎn)端存取,例如一些servlet容器對(duì)每個(gè)servlet使用完全不同的類裝載器,,這樣的話如果有兩個(gè)servlet訪問(wèn)一個(gè)單例類,,它們就都會(huì)有各自的實(shí)例。另外,,如果ClasicSingleton實(shí)現(xiàn)了java.io.Serializable接口,,那么這個(gè)類的實(shí)例就可能被序列化和復(fù)原。不管怎樣,,如果你序列化一個(gè)單例類的對(duì)象,,接下來(lái)復(fù)原多個(gè)那個(gè)對(duì)象,那你就會(huì)有多個(gè)單例類的實(shí)例,。 以上出現(xiàn)的問(wèn)題,,這里不進(jìn)行討論,這里主要討論線程安全問(wèn)題,。 問(wèn)題來(lái)了:就是例1中的ClassicSingleton類不是線程安全的,。如果兩個(gè)線程,,我們稱它們?yōu)榫€程1和線程2,在同一時(shí)間調(diào)用ClassicSingleton.getInstance()方法,,如果線程1先進(jìn)入if塊,,然后線程2進(jìn)行控制,那么就會(huì)有 ClassicSingleton的兩個(gè)的實(shí)例被創(chuàng)建,。 分析一下:
當(dāng)線程1剛進(jìn)入if語(yǔ)句時(shí)一直到當(dāng)new ClassicSingleton()剛結(jié)束,,但還沒(méi)有賦值給instance之前,這段時(shí)間里,,一旦發(fā)生了線程切換,,則線程2就會(huì)進(jìn)入if語(yǔ)句,這是instance仍然是null,,所以線程1和線程2都會(huì)創(chuàng)建一個(gè)ClassicSingleton實(shí)例,,也就是整個(gè)系統(tǒng)會(huì)有兩個(gè)ClassicSingleton實(shí)例被創(chuàng)建。 解決方法1: 可以使用線程同步的方法,,用關(guān)鍵字synchronized來(lái)使其同步,,這樣當(dāng)線程1進(jìn)入同步塊時(shí),線程2則無(wú)法進(jìn)入,。
解決方法2:用一個(gè)更簡(jiǎn)單、快速而又是線程安全的單例模式實(shí)現(xiàn)
這段代碼是線程安全的是因?yàn)殪o態(tài)成員變量一定會(huì)在類被第一次訪問(wèn)時(shí)被創(chuàng)建,。你得到了一個(gè)自動(dòng)使用了懶漢式實(shí)例化的線程安全的實(shí)現(xiàn),。 總結(jié)一下:Singleton單例模式為一個(gè)面向?qū)ο蟮膽?yīng)用程序提供了對(duì)象唯一的訪問(wèn)點(diǎn),不管它實(shí)現(xiàn)何種功能,,此種模式都為設(shè)計(jì)和開(kāi)發(fā)團(tuán)隊(duì)提供了共享的概念,。單例模式的要點(diǎn)有三個(gè):一是某個(gè)類只能有一個(gè)實(shí)例;二是它必須自行創(chuàng)建這個(gè)實(shí)例,;三是它必須自行向整個(gè)系統(tǒng)提供這個(gè)實(shí)例,。 |
|
來(lái)自: 看風(fēng)景D人 > 《設(shè)計(jì)模式》