簡單介紹七種單例模式

2021-10-07 14:39:38 字數 3204 閱讀 7290

單例模式相對來說,設計比較簡單,但是實現方式多種多樣,我們需要從執行緒安全、高效能、懶載入方面進行評估。

例項**如下:

public

final

class

singleton1

public

static singleton1 getinstance()

}

根據前面可以知道,在類的初始化階段類變數進行初始化,就是instance變數會被初始化,同時呢1k的空間data也被建立,我們可以寫段**測試下:

public

class

test

}

執行**會輸出:

singleton1 例項化
這也說明了class.forname方法會對類進行初始化

關於這點不懂得可以看看前面的部落格,有解釋到的,class.forname 和 classloader的區別

如果乙個類屬性較少,占用記憶體也較小,用餓漢式也未嘗不可。

總而言之,餓漢式不支援懶載入,可以保證多執行緒下只被載入一次,效能也比較高。

所謂懶漢式就是當你使用的時候再去建立,**如下

public

final

class

singleton2

public

static singleton2 getinstance()

return instance;

}}

這種方式會有乙個問題,當兩個執行緒都走在instance == null時,這個時候會建立兩個例項,執行緒不安全。

**如下

public

final

class

singleton3

//加鎖,每次只有乙個執行緒獲得

public

static

synchronized singleton3 getinstance()

return instance;

}}

這種方式的問題在於,synchronized的排他性,同一時刻,只能被乙個執行緒訪問,效能低下。

這種方法就是,在初次初始化的時候進行加鎖,之後就需要加鎖了,提高了效率。

public

final

class

singleton4

public

static singleton4 getinstance()

}}return instance;

}}

這種會出現空指標異常,我們來逐步分析下:

主要在於singleton = new singleton4()這句,這並非是乙個原子操作,事實上在 jvm 中這句話大概做了下面 3 件事情。

1. 給 singleton 分配記憶體

2. 呼叫 singleton 的建構函式來初始化成員變數,形成例項

3. 將singleton物件指向分配的記憶體空間(執行完這步 singleton才是非 null了)

在jvm的即時編譯器中存在指令重排序的優化。

也就是說上面的第二步和第三步的順序是不能保證的,最終的執行順序可能是 1-2-3 也可能是 1-3-2。如果是後者,則在 3 執行完畢、2 未執行之前,

被執行緒二搶占了,這時 instance 已經是非 null 了(但卻沒有初始化),所以執行緒二會直接返回 instance,然後使用,然後順理成章地報錯。

解決方案就是加上volatile,就可以了

public

final

class

singleton5

public

static singleton5 getinstance()

}}return instance;

}}

這了需要注意

volatile阻止的不是singleton = new singleton()這句話內部[1-2-3]的指令重排,而是保證了在乙個寫操作([1-2-3])完成之前,

不會呼叫讀操作(if (instance == null))。

holder方式借住類載入的特點,同一類載入器只會對同乙個類載入一次(這個時候可能被問到類載入器底層如何保證只被載入一次,可以翻翻我前面的部落格)

public

final

class

singleton6

public

static singleton6 getinstance()

}

holder會在編譯的時候被收集到方法中,該方法可以保證執行緒安全。

singleton6也可以保證懶載入,只有在初次呼叫getinstance方法時,才會初始化holder中的例項

利用自動序列化機制,保證了執行緒的絕對安全

public

enum singleton7

public

static

void

method()

public

static singleton7 getinstance()

}

這種方法如果呼叫了外部呼叫了靜態方法也會初始化,可以加上我們的holder模式

public

class

singleton8

public

static

void

method()

private

enum enumholder

public singleton8 getinstance()

}public singleton8 getinstance()

}

開發過程中,個人用的比較多的也是holder模式和列舉模式吧。

單例模式實現(七種)

單例模式確保乙個類只有乙個例項,並提供乙個全域性訪問點,實現單例模式的方法是私有化建構函式,通過getinstance 方法例項化物件,並返回這個例項 保證在jvm中只有乙個例項 優點 1 單例類只有乙個例項 2 共享資源,全域性使用 3 節省建立時間,提高效能 public class singl...

單例模式的七種寫法

第一種 懶漢,執行緒不安全 public class singleton public static singleton getinstance return instance 第二種 懶漢,執行緒安全 public class singleton public static synchronize...

七種單例模式的寫法

餓漢式 特點 在類載入時例項化,執行緒安全,如果沒有使用instance的話比較耗費資源 class singletondemo public static singletondemo getinstance 懶漢式 非執行緒安全 特點 使用時再例項化 class singletondemo pub...