概念:
單例模式(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 理...