總目錄:地址如下看總綱
1、餓漢模式:顧名思義,因?yàn)轲I了,就勤快
設(shè)計(jì)思路:實(shí)例在初始化的時(shí)候就已經(jīng)建好了,所以類加載較慢,但獲取對(duì)象的速度快。好處是沒有線程安全的問題(基于類加載機(jī)制),壞處是浪費(fèi)內(nèi)存空間,這時(shí)候初始化instance顯然沒有達(dá)到懶加載的效果。
public class Singleton {
private static Singleton instance = new Singleton ( );
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
補(bǔ)充:

2、懶漢模式(線程不安全)
設(shè)計(jì)思路:“比較懶”(用的時(shí)候才去檢查有沒有實(shí)例,如果有則返回,沒有則新建),懶漢模式聲明了一個(gè)靜態(tài)對(duì)象,在用戶第一次調(diào)用時(shí)初始化,雖然節(jié)約了資源,但第一次加載時(shí)需要實(shí)例化,反映稍慢一些,而且在多線程不能正常工作。
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton ( );
}
return instance;
}
}
3、懶漢模式(線程不安全),加了synchronized 修飾
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton ( );
}
return instance;
}
}
4、雙重檢查模式 (DCL):資源利用率高
設(shè)計(jì)思路:
1、此寫法在getSingleton方法中對(duì)singleton進(jìn)行了兩次判空,第一次是為了不必要的同步,第二次是在singleton等于null的情況下才創(chuàng)建實(shí)例。volatile關(guān)鍵字考慮了程序的正確性,但多少會(huì)影響性能。
2、某些情況會(huì)出現(xiàn)失效的問題,也就是DCL失效,在《java并發(fā)編程實(shí)踐》一書建議用靜態(tài)內(nèi)部類單例模式來替代DCL。
public class Singleton {
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton ( );
}
}
}
return instance;
}
}
5、靜態(tài)內(nèi)部類單例模式
設(shè)計(jì)思路:
第一次加載Singleton類時(shí)并不會(huì)初始化sInstance,只有第一次調(diào)用getInstance方法時(shí)虛擬機(jī)加載SingletonHolder 并初始化sInstance ,這樣不僅能確保線程安全也能保證Singleton類的唯一性,所以推薦使用靜態(tài)內(nèi)部類單例模式。
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.sInstance;
}
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton ( );
}
}
6、枚舉單例
設(shè)計(jì)思路:
1、默認(rèn)枚舉實(shí)例的創(chuàng)建是線程安全的,并且在任何情況下都是單例。不過上面的五種方式,有一種情況下他們會(huì)重新創(chuàng)建對(duì)象,那就是反序列化,將一個(gè)單例實(shí)例對(duì)象寫到磁盤(或者內(nèi)存)再讀回來,從而獲得了一個(gè)實(shí)例。反序列化操作提供了readResolve方法,這個(gè)方法可以讓開發(fā)人員控制對(duì)象的反序列化。在上述的幾個(gè)方法示例中如果要杜絕單例對(duì)象被反序列化是重新生成對(duì)象。
public enum Singleton {
INSTANCE;
public void doSomeThing() {
}
}
異常五種防止破壞單例的機(jī)制
private Object readResolve() throws ObjectStreamException {
return singleton;
}
補(bǔ)充:


參考博客:
https://www.cnblogs.com/xz816111/p/8470048.html
https://blog.csdn.net/itachi85/article/details/50510124?utm_medium
https://blog.csdn.net/huangbiao86/article/details/6896565
https://blog.csdn.net/u010002184/article/details/90748963
https://www.hollischuang.com/archives/2498
//韓順平的設(shè)計(jì)模式