一:何時用單例模式
只實例化一個對象時。幾乎所有的系統都會用到單例模式
二:模式
-
構造函數是私有的private
-
產生一個靜態的私有的對象
-
寫一個靜態的公有的方法,返回該類類型的實例化對象
三:分類:
懶漢式
- 存在多線程同步問題,可能會存在多個ClientManager 實例對象
- 當類第一次被加載時,不會爲ClientManager
實例化的對象分配內存,因爲在沒調用之前根本沒有實例化,當第一次調用getInstance()時,纔會爲ClientManager
實例化的對象分配內存,某段時間節省了內存空間
//私有的靜態成員
private static ClientManager instance = null;
// 定義私有構造方法(防止通過 new ClientManager()去實例化)
private ClientManager() {}
public static ClientManager getInstance() {
if(instance == null) {
synchronized(ClientManager.class){
if(instance == null){
instance = new ClientManager();
}
}
}
return instance;
}
餓漢式
- 不存在多線程同步問題
- 當類第一次被加載時,就會爲ClientManager 實例化的對象分配內存,某段時間浪費了內存空間
//私有的靜態成員
private static ClientManager instance = new ClientManager();
// 定義私有構造方法(防止通過 new ClientManager()去實例化)
private ClientManager() {}
public static ClientManager getInstance() {
//返回實例化對象
return instance;
}
四.優缺點
優點
- 節約系統資源,當 需要頻繁創建和銷燬的對象時單例模式無疑可以提高系統的性能
- 提供了對唯一實例的受控訪問
缺點
- 不適用於變化的對象,如果同一類型的對象總是要在不同的用例場景發生變化,單例就會引起數據的錯誤,不能保存彼此的狀態
- 不能被繼承,因爲構造函數是私有的,不能擴展
五.實際使用
在多線程中,線程池(數據庫連接池)就可以設置爲單例的,因爲線程池的作用就是統一管理多個線程,如果每來一個線程都去new一個新的線程池,就失去了線程池的意義。單例作用就是提供一個訪問對象的一個全局訪問點。在spring源碼中,IOC原理中如果<bean id="userservice" class="service.userService" scope="singleton">
設置bean是singleton,bean就是單例的,默認就是單例模式,但Spring框架對單例的支持是採用單例註冊表的方式進行實現的,即將產生的bean放到一個map中,每次取時會先去註冊表檢測有沒有該bean此時,檢測的過程上了synchronized鎖,如果沒有,再creat,有直接返回。