Java中單例(Singleton)模式是一種廣泛使用的設(shè)計(jì)模式。為了協(xié)調(diào)系統(tǒng)整體的行為,一些管理器和控制器常被設(shè)計(jì)成單例模式。
作用:保證 類在內(nèi)存中 的 實(shí)例對(duì)象的唯一性,節(jié)省了系統(tǒng)資源,提高系統(tǒng)性能。
一般適用場(chǎng)景:
-
1.避免同個(gè)類創(chuàng)建多個(gè)實(shí)例造成資源的浪費(fèi)。
-
2.避免多個(gè)實(shí)例因多次調(diào)用而出現(xiàn)錯(cuò)誤。
-
3.一般寫工具類,線程池,緩存,數(shù)據(jù)庫(kù)會(huì)用到。
基本的實(shí)現(xiàn)思路:
-
1.不準(zhǔn)在類的外部new對(duì)象 —— 構(gòu)造方法私有化
-
2.在類的內(nèi)部中提供創(chuàng)建對(duì)象的方法—— 通過new在本類中創(chuàng)建一個(gè)實(shí)例
-
3.對(duì)外部提供一個(gè)獲取該實(shí)例的方法 —— 定義公有方法返回創(chuàng)建的實(shí)例
餓漢模式與懶漢模式比較
前者在類裝載時(shí)就同時(shí)實(shí)例化,后者只有在第一次被使用時(shí)才會(huì)實(shí)例化。
1. 餓漢模式的優(yōu)點(diǎn)是沒有線程同步問題,缺點(diǎn)是用不到還會(huì)加載,資源浪費(fèi)。
2. 懶漢模式的優(yōu)點(diǎn)是實(shí)現(xiàn)了懶加載,節(jié)省資源,但是需要解決線程安全問題。
常見的七種單例模式實(shí)現(xiàn)套路
<1>餓漢式,沒有實(shí)現(xiàn)懶加載,代碼如下
<2>懶漢式
雖然實(shí)現(xiàn)了懶加載,線程安全問題還存在,舉例說(shuō)有兩個(gè)線程都剛好執(zhí)行完條件if(instance == null),然后準(zhǔn)備執(zhí)行instance = new Singleton() 語(yǔ)句,這樣的結(jié)果會(huì)導(dǎo)致內(nèi)存中實(shí)例化了兩個(gè)Singleton對(duì)象,為了解決線程不安全問題,可以對(duì)getInstance()方法進(jìn)行加鎖控制。
<3>懶漢式加鎖版
為getInstance方法加鎖雖然保證了線程安全,但是每次執(zhí)行g(shù)etInstance() 都需要同步,而實(shí)例化對(duì)象只需要執(zhí)行一次就夠了,以后獲取時(shí)直接return返回就好了,方法同步效率太低,一種改進(jìn)后的寫法是: synchronized (Singleton.class) { instance = new Singleton(); } 但是,這樣寫依然是線程不安全的,如果你還是想用懶漢式的話,推薦雙重檢查鎖定(DCL,Double Check Lock)。
<4>懶漢式雙重校驗(yàn)鎖(DCL模式)
在代碼中進(jìn)行了兩次if檢查,這樣就可以保證線程安全,初始化一次后,后面再次訪問時(shí),if檢查,直接return 實(shí)例化對(duì)象。volatile關(guān)鍵字是在JDK1.5后引入的,volatile關(guān)鍵字會(huì)屏蔽Java虛擬機(jī)所做的一些代碼優(yōu)化,會(huì)導(dǎo)致系統(tǒng)運(yùn)行效率降低,而更好的寫法是使用靜態(tài)內(nèi)部類來(lái)實(shí)現(xiàn)單例!
<5>靜態(tài)內(nèi)部類實(shí)現(xiàn)單例(推薦)
和餓漢式類似,都是通過JVM類加載機(jī)制來(lái)保證初始化實(shí)例的時(shí)候只存在一個(gè)線程,避免線程安全問題,餓漢式的Singleton類被加載時(shí),就會(huì)實(shí)例化,而靜態(tài)內(nèi)部類這種,當(dāng)Singleton類被加載時(shí),不會(huì)立即實(shí)例化,調(diào)用getInstance() 方法才會(huì)裝載SingletonHolder類,從而完成Singleton的實(shí)例化。
<6>枚舉實(shí)現(xiàn)單例
INSTANCE即為SingletonEnum類型的引用,得到它就可以調(diào)用枚舉中的方法。既避免了線程安全問題,還能防止反序列化重新創(chuàng)建新的對(duì)象,但同時(shí)也損失了類的一些特性,也沒有延時(shí)加載了。
<7>容器實(shí)現(xiàn)單例
將多種單例類型注入到一個(gè)全局的管理類中,在使用時(shí)根據(jù)key獲取相應(yīng)實(shí)例對(duì)象,有些類似工廠模式??梢怨芾矶喾N類型的單例,在使用時(shí)可以通過統(tǒng)一的接口進(jìn)行獲取,降低了使用成本,也對(duì)外部隱藏了具體實(shí)現(xiàn),耦合度得到了降低。