物件池模式(Object Pool Pattern)。
阿新 • • 發佈:2018-11-08
定義
物件池模式,或者稱為物件池服務,通過迴圈使用物件,減少資源在初始化和釋放時的昂貴損耗。
注意:這裡的“昂貴”可能是時間效益(如效能),也可能是空間效益(如並行處理),在大多的情況下,“昂貴”指效能。
簡單的說,在需要時,從池中提取;不用時,放回池中,等待下一個請求。典型例子是連線池和執行緒池,這是我們開發中經常接觸到的。
通用原始碼
物件池提供兩個公共的方法:checkOut負責從池中提取物件,checkIn負責把回收物件(當然,很多時候checkIn已經自動化處理,不需要顯式宣告,如連線池),物件池程式碼如下所示。
public abstract class ObjectPool<T> { // 容器,容納物件 private Hashtable<T, ObjectStatus> pool = new Hashtable<T, ObjectStatus>(); /** * 初始化時建立物件,並放入到池中 */ public ObjectPool() { this.pool.put(create(), new ObjectStatus()); } /** * 從Hashtable中取出空閒元素 * * @return */ public synchronized T checkOut() { // 這是最簡單的策略 for (T t : this.pool.keySet()) { if (this.pool.get(t).validate()) { this.pool.get(t).setUsing(); return t; } } return null; } /** * 歸還物件 * * @param t */ public synchronized void checkIn(T t) { this.pool.get(t).setFree(); } class ObjectStatus { /** * 佔用 */ public void setUsing() { } /** * 釋放 */ public void setFree() { // 注意:若T是有狀態,則需要回歸到初始化狀態 } /** * 檢查是否可用 * * @return */ public boolean validate() { return false; } } /** * 建立池化物件 * * @return */ public abstract T create(); }
這是一個簡單地池物件實現,在實際應用中還需要考慮池的最小值、最大值、池化物件狀態(若有的話,需要重點考慮)、異常處理(如滿池情況)等方面,特別是池化物件狀態,若是有狀態的業務物件則需要重點關注。
最佳實踐
把物件池化的本意是期望一次性初始化所有物件,減少物件在初始化上的昂貴效能開銷,從而提高系統整體效能。然而池化處理本身也要付出代價,因此,並非任何情況下都適合採用物件池化。
通常情況下,在重複生成物件的操作成為影響效能的關鍵因素時,才適合進行物件池化。但是若池化所能帶來的效能提高並不顯著或重要的話,建議放棄物件池化技術,以保持程式碼的簡明,轉而使用更好的硬體來提高效能為佳。
物件池技術在Java領域已經非常成熟,只要做到企業級開發的人員,基本都用過C3P0、DBCP、Proxool等連線池,也配置過minPoolSize、maxPoolSize等引數,這是物件池模式的典型應用。在實際開發中若需要物件池,建議使用common-pool工具包來實現,簡單、快捷、高效。