1. 程式人生 > >物件池模式(Object Pool Pattern)。

物件池模式(Object Pool Pattern)。

定義

物件池模式,或者稱為物件池服務,通過迴圈使用物件,減少資源在初始化和釋放時的昂貴損耗。

注意:這裡的“昂貴”可能是時間效益(如效能),也可能是空間效益(如並行處理),在大多的情況下,“昂貴”指效能。

簡單的說,在需要時,從池中提取;不用時,放回池中,等待下一個請求。典型例子是連線池和執行緒池,這是我們開發中經常接觸到的。

通用原始碼

物件池提供兩個公共的方法: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工具包來實現,簡單、快捷、高效。