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

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

5種實現(xiàn)單例模式的方式

2022-12-24 06:38 作者:我是大彬呀  | 我要投稿

單例模式

單例模式(Singleton),目的是為了保證在一個進程中,某個類有且僅有一個實例。

由于這個類只有一個實例,所以不能讓調(diào)用方使用new Xxx()來創(chuàng)建實例。所以,單例的構(gòu)造方法必須是private,這樣就防止了調(diào)用方自己創(chuàng)建實例。

單例模式的實現(xiàn)需要三個必要的條件

  1. 單例類的構(gòu)造函數(shù)必須是私有的,這樣才能將類的創(chuàng)建權(quán)控制在類的內(nèi)部,從而使得類的外部不能創(chuàng)建類的實例。

  2. 單例類通過一個私有的靜態(tài)變量來存儲其唯一實例。

  3. 單例類通過提供一個公開的靜態(tài)方法,使得外部使用者可以訪問類的唯一實例。

另外,實現(xiàn)單例類時,還需要考慮三個問題:

  • 創(chuàng)建單例對象時,是否線程安全

  • 單例對象的創(chuàng)建,是否延時加載

  • 獲取單例對象時,是否需要加鎖

下面介紹幾種實現(xiàn)單例模式的方式。

餓漢模式

JVM在類的初始化階段,會執(zhí)行類的靜態(tài)方法。在執(zhí)行類的初始化期間,JVM會去獲取Class對象的鎖。這個鎖可以同步多個線程對同一個類的初始化。

餓漢模式只在類加載的時候創(chuàng)建一次實例,沒有多線程同步的問題。單例沒有用到也會被創(chuàng)建,而且在類加載之后就被創(chuàng)建,內(nèi)存就被浪費了。

public?class?Singleton?{??
????private?static?Singleton?instance?=?new?Singleton();??
????private?Singleton()?{}??
????public?static?Singleton?newInstance()?{
????????return?instance;??
????}??
}

餓漢式單例的優(yōu)點

  • 單例對象的創(chuàng)建是線程安全的;

  • 獲取單例對象時不需要加鎖。

餓漢式單例的缺點:單例對象的創(chuàng)建,不是延時加載。

懶漢式

與餓漢式思想不同,懶漢式支持延時加載,將對象的創(chuàng)建延遲到了獲取對象的時候。不過為了線程安全,在獲取對象的操作需要加鎖,這就導(dǎo)致了低性能。

public?class?Singleton?{?
??private?static?final?Singleton?instance;
??
??private?Singleton?()?{}
??
??public?static?synchronized?Singleton?getInstance()?{????
????if?(instance?==?null)?{??????
??????instance?=?new?Singleton();????
????}????

????return?instance;??
??}
}

上述代碼加的鎖只有在第一次創(chuàng)建對象時有用,而之后每次獲取對象,其實是不需要加鎖的(雙重檢查鎖定優(yōu)化了這個問題)。

懶漢式單例優(yōu)點

  • 對象的創(chuàng)建是線程安全的。

  • 支持延時加載。

懶漢式單例缺點

  • 獲取對象的操作被加上了鎖,影響了并發(fā)性能。

雙重檢查鎖定

雙重檢查鎖定將懶漢式中的 synchronized 方法改成了 synchronized 代碼塊。如下:

public?class?Singleton?{??
????private?static?volatile?Singleton?instance?=?null;??//volatile
????private?Singleton(){}??
????public?static?Singleton?getInstance()?{??
????????if?(instance?==?null)?{??
????????????synchronized?(Singleton.class)?{??
????????????????if?(instance?==?null)?{
????????????????????instance?=?new?Singleton();??
????????????????}??
????????????}??
????????}??
????????return?instance;??
????}??
}??

雙重校驗鎖先判斷 instance 是否已經(jīng)被實例化,如果沒有被實例化,那么才對實例化語句進行加鎖。

instance使用static修飾的原因:getInstance為靜態(tài)方法,因為靜態(tài)方法的內(nèi)部不能直接使用非靜態(tài)變量,只有靜態(tài)成員才能在沒有創(chuàng)建對象時進行初始化,所以返回的這個實例必須是靜態(tài)的。

為什么兩次判斷instance == null

TimeThread AThread BT1檢查到instance為空
T2
檢查到instance為空T3
初始化對象AT4
返回對象AT5初始化對象B
T6返回對象B

new Singleton()會執(zhí)行三個動作:分配內(nèi)存空間、初始化對象和對象引用指向內(nèi)存地址。

memory?=?allocate();??//?1:分配對象的內(nèi)存空間
ctorInstance(memory);??//?2:初始化對象
instance?=?memory;????//?3:設(shè)置instance指向剛分配的內(nèi)存地址

由于指令重排優(yōu)化的存在,導(dǎo)致初始化對象和將對象引用指向內(nèi)存地址的順序是不確定的。在某個線程創(chuàng)建單例對象時,會為該對象分配了內(nèi)存空間并將對象的字段設(shè)置為默認(rèn)值。此時就可以將分配的內(nèi)存地址賦值給instance字段了,然而該對象可能還沒有初始化。若緊接著另外一個線程來調(diào)用getInstance,取到的是未初始化的對象,程序就會出錯。volatile 可以禁止指令重排序,保證了先初始化對象再賦值給instance變量。

TimeThread AThread BT1檢查到instance為空
T2獲取鎖
T3再次檢查到instance為空
T4為instance分配內(nèi)存空間
T5將instance指向內(nèi)存空間
T6
檢查到instance不為空T7
訪問instance(此時對象還未完成初始化)T8初始化instance

雙重檢查鎖定單例優(yōu)點

  • 對象的創(chuàng)建是線程安全的。

  • 支持延時加載。

  • 獲取對象時不需要加鎖。

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

它與餓漢模式一樣,也是利用了類初始化機制,因此不存在多線程并發(fā)的問題。不一樣的是,它是在內(nèi)部類里面去創(chuàng)建對象實例。這樣的話,只要應(yīng)用中不使用內(nèi)部類,JVM就不會去加載這個單例類,也就不會創(chuàng)建單例對象,從而實現(xiàn)懶漢式的延遲加載。也就是說這種方式可以同時保證延遲加載和線程安全。

基于類初始化的方案的實現(xiàn)代碼更簡潔。

public?class?Instance?{
????private?static?class?InstanceHolder?{
????????public?static?Instance?instance?=?new?Instance();
????}
????private?Instance()?{}
????public?static?Instance?getInstance()?{
????????return?InstanceHolder.instance?;??//?這里將導(dǎo)致InstanceHolder類被初始化
????}
}

如上述代碼,InstanceHolder 是一個靜態(tài)內(nèi)部類,當(dāng)外部類 Instance 被加載的時候,并不會創(chuàng)建 InstanceHolder 實例對象。

只有當(dāng)調(diào)用 getInstance() 方法時,InstanceHolder 才會被加載,這個時候才會創(chuàng)建 Instance。Instance 的唯一性、創(chuàng)建過程的線程安全性,都由 JVM 來保證。

靜態(tài)內(nèi)部類單例優(yōu)點

  • 對象的創(chuàng)建是線程安全的。

  • 支持延時加載。

  • 獲取對象時不需要加鎖。

枚舉

用枚舉來實現(xiàn)單例,是最簡單的方式。這種實現(xiàn)方式通過 Java 枚舉類型本身的特性,保證了實例創(chuàng)建的線程安全性和實例的唯一性。

public?enum?Singleton?{
??INSTANCE;?//?該對象全局唯一
}


5種實現(xiàn)單例模式的方式的評論 (共 條)

分享到微博請遵守國家法律
静宁县| 绥江县| 林周县| 石首市| 福建省| 临西县| 黑龙江省| 宁乡县| 日土县| 庄河市| 泸西县| 永春县| 连城县| 天柱县| 富锦市| 寿阳县| 巴南区| 尼玛县| 南康市| 嘉峪关市| 越西县| 嘉荫县| 油尖旺区| 濉溪县| 宝坻区| 奈曼旗| 来安县| 兴和县| 青河县| 道真| 茌平县| 建宁县| 措美县| 新巴尔虎左旗| 西平县| 凤城市| 哈巴河县| 宜春市| 天长市| 昌邑市| 新安县|