Spring學習基礎(三) 單例模式

2021-10-08 19:49:46 字數 2913 閱讀 6224

概念:

單例模式(singleton pattern):確保某乙個類只有乙個例項,而且自行例項化並向整個系統提供這個例項,這個類稱為單例類,他提供了全域性訪問的方法。單例模式是一種物件建立型模式。

spring依賴注入bean例項預設都是單例的,所以我們這一章回顧一下單例模式。

傳統建立類**

package pattern;

public class case_1

}class singleten

在上段**中,我們每次new singleten(),都會建立乙個singleten例項,顯然不符合乙個類只有乙個例項的要求。所以作出如下修改:

/**

* 單例模式例項

*/public class case_1

}/**

* 描述:單例類(餓漢模式)

* @author yangfan

* */

class singleten

//stap3.提供外界可以獲得該例項的方法

public static singleten getinstance(

)}

單例模式的寫法有很多種,上述**是乙個簡單的餓漢模式的實現**,實現步驟總共有三步:

與餓漢模式相對應的還有懶漢模式,懶漢模式有延遲載入的意思,具體**如下:

/**

* 懶漢模式

*/private static singleten singleten = new singleten();

private singleten();

public static singleten getinstance(

)return singleten;

}

如果建立單例物件會消耗大量資源,那麼懶漢模式的延遲建立是個不錯的選擇

但是懶漢模式有個明顯的問題,就是沒有考慮到執行緒的安全問題,在多執行緒的併發情況下,會併發呼叫getinstance()方法,從而導致系統同時建立多個單例類例項,這顯然不符合要求。

我們可以通過給getinstance()新增鎖來解決該問題:

/**

* 懶漢模式(新增synchronized鎖)

*/private static singleten singleten = new singleten();

private singleten();

public static synchronized singleten getinstance(

)return singleten;

}

新增synchronized鎖雖然可以保證執行緒安全,但是每次呼叫個體instance()方法時,都會有加鎖和解鎖操作,其次synchronized鎖是新增在方法上,鎖的範圍過大,而單例類是全域性唯一的。

因此,需要使用「雙重校驗鎖」進行優化:

/**

* 雙重校驗鎖(指令重排問題)

* */

private static singleten singleten = new singleten();

private singleten();

public static singleten getinstance()}

}return singleten;

}

以上雙重校驗鎖或出現指令重排的問題:

指令重排:指jvm為了優化指令,提高程式執行效率,在不影響單執行緒程式執行結果的前提下,盡可能的提高並行度

singleten = new singleten()可以抽象為以下jvm指令:

//1.分配物件的記憶體空間

memory = allocate();

//2.初始化物件

ctorinstance(memory)

;//3.設定instance指向剛分配的記憶體位址

singleten = memory;

上述操作2依賴於操作1,但是操作3並不依賴於操作2,所以jvm是可以針對他們進行指令的優化重新排序

排序後步驟如下

//1.分配物件的記憶體空間

memory =allocate();

指向剛分配的位址,此時物件還沒有初始化

singleten = memory;

//3.初始化物件

ctorinstance(memory)

;

為了解決指令重排問題,可以使用volatile關鍵字修飾singleten欄位。volatile關鍵字的乙個語義就是禁止指令的重新排序優化,阻止jvm指令重排,修改如下:

/**

* 雙重校驗鎖(volatile解決指令重排問題)

*/private static volatile singleten singleten = new singleten();

private singleten();

public static singleten getinstance()}

}return singleten;

}

當然,除了雙重校驗鎖的方法,還有一種比較好的單例模式寫法:

靜態內部類的單例模式

/**

* 靜態內部類的單例模式(推薦寫法)

*///2.私有的靜態內部類,類載入器負責加鎖

private static class singletenholder

//1.構造方法私有化

private singleten();

//3.自行對外提高例項

public static singleten getinstance(

)

spring 單例模式

單例模式,在spring 中其實是scope 作用範圍 引數的預設設定值 每個bean定義只生成乙個物件例項,每次getbean請求獲得的都是此例項 餓漢模式 spring singleton的預設是餓漢模式 啟動容器時 即例項化容器時 為所有spring配置檔案中定義的bean都生成乙個例項 懶漢...

Spring 單例模式

jvm的工作原理 a 類載入器 通過類載入器將編譯好的位元組碼檔案載入到jvm中。b 位元組碼校驗器 校驗載入過來的位元組碼的合法,如是否損壞或者被病毒篡改過等。如果校驗失敗則不會繼續執行了。c 直譯器 解釋執行位元組碼生成目標平台的機器碼執行。靜態成員在什麼時候就存在了?在位元組碼檔案被成功載入到...

Spring 單例模式

spring物件預設是單例的。可以通過scope屬性更改為多例。通過配置檔案 bean id test class test.test scope prototype bean 通過註解 controller scope prototype public class testcontroller 理...