对象池模式(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工具包来实现,简单、快捷、高效。

猜你喜欢

转载自blog.csdn.net/en_joker/article/details/83008686
今日推荐