最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

java程序員最常使用的設(shè)計(jì)模式之單例模式總結(jié)

2023-04-01 00:10 作者:小劉Java之路  | 我要投稿

java虛擬機(jī)之jvm面試關(guān)鍵內(nèi)容總結(jié)

bat大廠面試高頻90題,測(cè)測(cè)你的打幾分

HashMap原理,使用說(shuō)明,源碼驗(yàn)證

Spring AOP和Spring - 動(dòng)態(tài)代理總結(jié)

java程序在jvm類加載順序總結(jié)

SpringMVC 框架介紹

程序員必備的工具HuTool常用功能總結(jié)

1 創(chuàng)建型模式

創(chuàng)建型模式的主要關(guān)注點(diǎn)是“怎樣創(chuàng)建對(duì)象?”,它的主要特點(diǎn)是“將對(duì)象的創(chuàng)建與使用分離”。這樣可以降低系統(tǒng)的耦合度,使用者不需要關(guān)注對(duì)象的創(chuàng)建細(xì)節(jié)。

創(chuàng)建型模式分為:

  1. 單例模式

  2. 工廠方法模式

  3. 抽象工廠模式

  4. 原型模式

  5. 建造者模式

1.1 單例設(shè)計(jì)模式

單例模式(Singleton Pattern)是 Java 中最簡(jiǎn)單的設(shè)計(jì)模式之一。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。這種模式涉及到一個(gè)單一的類,該類負(fù)責(zé)創(chuàng)建自己的對(duì)象,同時(shí)確保只有單個(gè)對(duì)象被創(chuàng)建。這個(gè)類提供了一種訪問(wèn)其唯一的對(duì)象的方式,可以直接訪問(wèn),不需要實(shí)例化該類的對(duì)象。

1.1.1 單例模式的結(jié)構(gòu)

單例模式的主要有以下角色:?jiǎn)卫悺V荒軇?chuàng)建一個(gè)實(shí)例的類,訪問(wèn)類。使用單例類。

1.1.2 單例模式的實(shí)現(xiàn)

單例設(shè)計(jì)模式分類兩種:

餓漢式:類加載就會(huì)導(dǎo)致該單實(shí)例對(duì)象被創(chuàng)建;

懶漢式:類加載不會(huì)導(dǎo)致該單實(shí)例對(duì)象被創(chuàng)建,而是首次使用該對(duì)象時(shí)才會(huì)創(chuàng)建。

  • 餓漢式-方式1(靜態(tài)變量方式)

說(shuō)明:

該方式在成員位置聲明Singleton類型的靜態(tài)變量,并創(chuàng)建Singleton類的對(duì)象instance。instance對(duì)象是隨著類的加載而創(chuàng)建的。如果該對(duì)象足夠大的話,而一直沒(méi)有使用就會(huì)造成內(nèi)存的浪費(fèi)。


  • 餓漢式-方式2(靜態(tài)代碼塊方式)

說(shuō)明:

該方式在成員位置聲明Singleton類型的靜態(tài)變量,而對(duì)象的創(chuàng)建是在靜態(tài)代碼塊中,也是對(duì)著類的加載而創(chuàng)建。所以和餓漢式的方式1基本上一樣,當(dāng)然該方式也存在內(nèi)存浪費(fèi)問(wèn)題。


  • 懶漢式-方式1(線程不安全)

說(shuō)明:

從上面代碼我們可以看出該方式在成員位置聲明Singleton類型的靜態(tài)變量,并沒(méi)有進(jìn)行對(duì)象的賦值操作,那么什么時(shí)候賦值的呢?當(dāng)調(diào)用getInstance()方法獲取Singleton類的對(duì)象的時(shí)候才創(chuàng)建Singleton類的對(duì)象,這樣就實(shí)現(xiàn)了懶加載的效果。但是,如果是多線程環(huán)境,會(huì)出現(xiàn)線程安全問(wèn)題。


  • 懶漢式-方式2(線程安全)

該方式也實(shí)現(xiàn)了懶加載效果,同時(shí)又解決了線程安全問(wèn)題。但是在getInstance()方法上添加了synchronized關(guān)鍵字,導(dǎo)致該方法的執(zhí)行效果特別低。從上面代碼我們可以看出,其實(shí)就是在初始化instance的時(shí)候才會(huì)出現(xiàn)線程安全問(wèn)題,一旦初始化完成就不存在了。

  • 懶漢式-方式3(雙重檢查鎖)

再來(lái)討論一下懶漢模式中加鎖的問(wèn)題,對(duì)于 getInstance() 方法來(lái)說(shuō),絕大部分的操作都是讀操作,讀操作是線程安全的,所以我們沒(méi)必讓每個(gè)線程必須持有鎖才能調(diào)用該方法,我們需要調(diào)整加鎖的時(shí)機(jī)。由此也產(chǎn)生了一種新的實(shí)現(xiàn)模式:雙重檢查鎖模式

雙重檢查鎖模式是一種非常好的單例實(shí)現(xiàn)模式,解決了單例、性能、線程安全問(wèn)題,上面的雙重檢測(cè)鎖模式看上去完美無(wú)缺,其實(shí)是存在問(wèn)題,在多線程的情況下,可能會(huì)出現(xiàn)空指針問(wèn)題,出現(xiàn)問(wèn)題的原因是JVM在實(shí)例化對(duì)象的時(shí)候會(huì)進(jìn)行優(yōu)化和指令重排序操作。要解決雙重檢查鎖模式帶來(lái)空指針異常的問(wèn)題,只需要使用 volatile 關(guān)鍵字, volatile 關(guān)鍵字可以保證可見(jiàn)性和有序性。

小結(jié):

添加 volatile 關(guān)鍵字之后的雙重檢查鎖模式是一種比較好的單例實(shí)現(xiàn)模式,能夠保證在多線程的情況下線程安全也不會(huì)有性能問(wèn)題。


  • 懶漢式-方式4(靜態(tài)內(nèi)部類方式)

靜態(tài)內(nèi)部類單例模式中實(shí)例由內(nèi)部類創(chuàng)建,由于 JVM 在加載外部類的過(guò)程中, 是不會(huì)加載靜態(tài)內(nèi)部類的, 只有內(nèi)部類的屬性/方法被調(diào)用時(shí)才會(huì)被加載, 并初始化其靜態(tài)屬性。靜態(tài)屬性由于被 static 修飾,保證只被實(shí)例化一次,并且嚴(yán)格保證實(shí)例化順序。

說(shuō)明:

第一次加載Singleton類時(shí)不會(huì)去初始化INSTANCE,只有第一次調(diào)用getInstance,虛擬機(jī)加載SingletonHolder并初始化INSTANCE,這樣不僅能確保線程安全,也能保證 Singleton 類的唯一性。


小結(jié):

靜態(tài)內(nèi)部類單例模式是一種優(yōu)秀的單例模式,是開(kāi)源項(xiàng)目中比較常用的一種單例模式。在沒(méi)有加任何鎖的情況下,保證了多線程下的安全,并且沒(méi)有任何性能影響和空間的浪費(fèi)。


枚舉方式

枚舉類實(shí)現(xiàn)單例模式是極力推薦的單例實(shí)現(xiàn)模式,因?yàn)槊杜e類型是線程安全的,并且只會(huì)裝載一次,設(shè)計(jì)者充分的利用了枚舉的這個(gè)特性來(lái)實(shí)現(xiàn)單例模式,枚舉的寫法非常簡(jiǎn)單,而且枚舉類型是所用單例實(shí)現(xiàn)中唯一一種不會(huì)被破壞的單例實(shí)現(xiàn)模式。

說(shuō)明:

枚舉方式屬于餓漢式方式。


1.1.3 存在的問(wèn)題

1.1.3.1 問(wèn)題演示

  • 破壞單例模式:

使上面定義的單例類(Singleton)可以創(chuàng)建多個(gè)對(duì)象,枚舉方式除外。有兩種方式,分別是序列化和反射。

序列化反序列化

Singleton類:

Test類:

上面代碼運(yùn)行結(jié)果是false,表明序列化和反序列化已經(jīng)破壞了單例設(shè)計(jì)模式。


  • 反射

Singleton類:

Test類:

上面代碼運(yùn)行結(jié)果是false,表明序列化和反序列化已經(jīng)破壞了單例設(shè)計(jì)模式

注意:枚舉方式不會(huì)出現(xiàn)這兩個(gè)問(wèn)題。


1.1.3.2 問(wèn)題的解決

序列化、反序列方式破壞單例模式的解決方法

在Singleton類中添加readResolve()方法,在反序列化時(shí)被反射調(diào)用,如果定義了這個(gè)方法,就返回這個(gè)方法的值,如果沒(méi)有定義,則返回新new出來(lái)的對(duì)象。

Singleton類:

源碼解析:

ObjectInputStream類

? ? ? ? ? ? ?

反射方式破解單例的解決方法

? ??

? ??


說(shuō)明:


這種方式比較好理解。當(dāng)通過(guò)反射方式調(diào)用構(gòu)造方法進(jìn)行創(chuàng)建創(chuàng)建時(shí),直接拋異常。不運(yùn)行此中操作。


1.1.4 JDK源碼解析-Runtime類

Runtime類就是使用的單例設(shè)計(jì)模式。通過(guò)源代碼查看使用的是哪種單例模式

從上面源代碼中可以看出Runtime類使用的是餓漢式(靜態(tài)屬性)方式來(lái)實(shí)現(xiàn)單例模式的。


使用Runtime類中的方法

java虛擬機(jī)之jvm面試關(guān)鍵內(nèi)容總結(jié)

bat大廠面試高頻90題,測(cè)測(cè)你的打幾分

HashMap原理,使用說(shuō)明,源碼驗(yàn)證

Spring AOP和Spring - 動(dòng)態(tài)代理總結(jié)

java程序在jvm類加載順序總結(jié)

SpringMVC 框架介紹

程序員必備的工具HuTool常用功能總結(jié)


java程序員最常使用的設(shè)計(jì)模式之單例模式總結(jié)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
株洲市| 武陟县| 英吉沙县| 渭南市| 塘沽区| 内丘县| 龙泉市| 岳普湖县| 祁门县| 合阳县| 乡城县| 华容县| 穆棱市| 卢氏县| 新野县| 高密市| 遂溪县| 玉龙| 汝阳县| 法库县| 靖宇县| 永济市| 庆城县| 磐安县| 石嘴山市| 陆川县| 鹤庆县| 怀柔区| 柯坪县| 当雄县| 临邑县| 盐津县| 伊宁县| 平湖市| 行唐县| 郴州市| 大埔县| 永修县| 江北区| 清徐县| 隆化县|