Commons Pool处理对象池化分析(1)

参考:

http://www.ibm.com/developerworks/cn/java/l-common-pool/

http://www.blogjava.net/changedi/archive/2011/05/06/349665.html


对象池化技术:

将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频繁创建对象所造成的开销。用于充当保存对象的“容器”的对象,被称为“对象池”(Object Pool,或简称Pool)。

为什么要使用池化技术

有时候初始化一些对象可以能会消耗很多的时间,比如对数据库的操作需要 :

1、和数据库建立连接

2、对数据进行查询

3、和数据库断开连接

一般情况下数据库和java程序都不在一台机器上,这个时候需要通过网络来访问,建立连接消耗的时间比较长,如果每次查询都需要重新建立连接,不仅服务器压力最大,

而且对于用户来说,过慢的访问速度大大影响了体验效果。

这个时候就需要使用池化技术来加快访问速度,原理:在系统启动的时候建立若干个数据库连接的对象并且保存起来(若干的概念就引申为“池”可以是List等),某个用户需要对数据库操作的时候直接在这个“池”里面拿到一个连接对象,待操作完成之后,将这个连接归还给“池”。这样一来程序和数据库建立连接对象的时间交给了系统启动,完成之后不直接销毁而是放回原处,这样用户和数据库建立连接的过程,转变为了从“池”里面拿放的过程,大大提供了服务器效率,从而增强了用户体验。


使用commons-pool实现连接池:

下载地址:http://commons.apache.org/pool/


Commons-Pool 提供了通用对象池接口,一个用于创建模块化对象池的工具包,以及通常的对象池实

  • 所含包数:2个(org.apache.commons.pool和org.apache.commons.pool.impl)
  • 所含类数:21个(其中有4个抽象类和6个接口)
如果使用池化技术的话一般涉及到如下几个接口

PoolableObjectFactory、ObjectPool和ObjectPoolFactory

在Pool组件中,对象池化的工作被划分给了三类对象:

  • PoolableObjectFactory用于管理被池化的对象的产生、激活、挂起、校验和销毁;
  • ObjectPool用于管理要被池化的对象的借出和归还,并通知PoolableObjectFactory完成相应的工作;
  • ObjectPoolFactory则用于大量生成相同类型和设置的ObjectPool。

相应地,使用Pool组件的过程,也大体可以划分成“创立PoolableObjectFactory”、“使用ObjectPool”和可选的“利用ObjectPoolFactory”三种动作。

举个实际点的例子说明 这几个类之间的关系,电脑向手机、移动硬盘等移动设备复制文件,这些移动产品最终都是通过统一的usb接口跟电脑连接,可见和电脑相连的那一端接口是统一,只不过和不同设备连接的那一端不同而已,因此各大移动设备厂商只要保证和电脑连接的那端接口是统一就行,至于和各种移动设备连接的那一段是什么口都不要紧,这个做好了电脑就可以对移动设备的存储空间进行操作了,怎么操作是电脑的事情和移动设备无关。

PoolableObjectFactory相当于和电脑连接的那一端usb,各大移动厂商根据自己设备的特点实现PoolableObjectFactory接口里面的方法就可以和电脑连接了,而ObjectPool相当于电脑,将PoolableObjectFactory的实例放在里面,电脑就可以操作移动设备了。


同理比如一个Bean需要使用池化技术来管理,对于这个Bean对象只要实现PoolableObjectFactory接口,而具体怎么去产生、激活、挂起、校验和销毁,的操作是这个Bean对象自己的业务。

将PoolableObjectFactory接口的引用放在ObjectPool里面(一般在实例化ObjectPool或者通过ObjectPool的setFactory方法将其设置进去),由此可知这个对象实际上是用来管理被池化对象的(对象借出和归还),相当于电脑管理移动设备一样。

被池化的对象是通过实现PoolableObjectFactory来完成的,如果需要生成大量相同设置和类型的ObjectPool(相当于生产电脑)最好是用ObjectPoolFactory工厂来创建。


最简单池化技术的使用

1、创建一个实现了PoolableObjectFactory接口的类PoolableObjectFactorySample被池化对象是StringBuilder。 

public class PoolableObjectFactorySample implements PoolableObjectFactory<StringBuilder>  {
	private static int counter = 0;

	/**
	 * 这个方法用于在必要时产生新的对象
	 */
	public StringBuilder makeObject() throws Exception {
		StringBuilder obj = new StringBuilder();
		obj.append(counter++);
		System.err.println("Making Object " + obj.toString());
		return obj;
	}

	/**
	 * 这个方法用于销毁被validateObject判定为已失效的对象
	 */
	public void destroyObject(StringBuilder obj) throws Exception {
	    System.err.println("Destroying Object " + obj);
	}
	/**
	 * 这个方法用于校验一个具体的对象是否仍然有效,已失效的对象会被自动交给destroyObject方法销毁
	 */
	public boolean validateObject(StringBuilder obj) {
		/* 以1/2的概率将对象判定为失效 */
		boolean result = (Math.random() > 0.5);
		System.err.println("Validating Object " + obj + " : " + result);
		return result;
	}

	/**
	 * 这个方法用于将对象“激活”――设置为适合开始使用的状态
	 */
	public void activateObject(StringBuilder obj) throws Exception {
		System.err.println("Activating Object " + obj);
	}

	/**
	 * 这个方法用于将对象“挂起”――设置为适合开始休眠的状态
	 */
	public void passivateObject(StringBuilder obj) throws Exception {
		System.err.println("Passivating Object " + obj);
	}
}

PoolableObjectFactory 包括

创建 T makeObject() 池化对象。

销毁 destroyObject(T obj)池化对象。

验证 boolean validateObject(T obj)池化对象。

激活void activateObject(T obj)池化对象


2、开始池化:

public class ObjectPoolSample {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 生成一个要PoolableObjectFactory类的实例
		PoolableObjectFactory<StringBuilder> factory = new PoolableObjectFactorySample();
		// 利用这个PoolableObjectFactory实例为参数,
		//生成一个实现了ObjectPool接口的类(例如StackObjectPool)的实例,作为对象池
		ObjectPool<StringBuilder> pool = new StackObjectPool<StringBuilder>(factory);
                 //使用StackObjectPool工厂来实现
                //ObjectPoolFactory poolFactory = new StackObjectPoolFactory(factory);
                //ObjectPool pool = poolFactory.createPool();

		StringBuilder obj = null;
		try {
			for (long i = 0; i < 100; i++) {
				   System.out.println("== " + i + " ==");
					// 需要从对象池中取出对象时,调用该对象池的Object borrowObject()方法。
					obj = pool.borrowObject();
					System.out.println(obj.toString());
					if((i&1)==0)
					// 需要将对象放回对象池中时,调用该对象池的void returnObject(Object obj)方法
					pool.returnObject(obj);
				 System.out.println(obj);
			}
			obj = null;// 明确地设为null,作为对象已归还的标志
			// 当不再需要使用一个对象池时,调用该对象池的void close()方法,释放它所占据的资源。

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (obj != null) {// 避免将一个对象归还两次
					pool.returnObject(obj);
				}
				pool.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

}

StackObjectPool实现了ObjectPool接口,是系统默认定义里面保存所有池化了的对象,用Stack(堆)来存储,主要方法:

T borrowObject()从池中获取一个对象。

void returnObject(T obj) 将使用了的对象放入池中。

void invalidateObject(T obj) 销毁某个对象。

void close()来关闭不再需要的对象池

void clear()来清空池中的对象。
int getNumActive()来查询已借出的对象数。

int getNumIdle()来查询正在休眠的对象数。

void setFactory(PoolableObjectFactory factory)来设置要用的PoolableObjectFactory实例



很多时候我们不需要实现PoolableObjectFactory接口里面的所有方法, 幸好系统提供了  BasePoolableObjectFactory我们只需要继承就行了,根据具体情况编写代码。

例如:

public class BasePoolableObjectFactorySample extends BasePoolableObjectFactory {
	private int counter = 0;

	public Object makeObject() throws Exception {
		return String.valueOf(counter++);
	}

}
我们只需要实现makeObject方法。


UML图

根据设计模式来考虑:

PoolableObjectFactory相当于产品的工厂,负责产品的细节部分。

而ObjectPool相当于管理在PoolableObjectFactory中生产出来的产品
而ObjectPoolFactory就是生产管理者的工厂。

与此对应这些接口有的有抽象的类:

PoolableObjectFactory------BasePoolableObjectFactory

ObjectPool---------------------BaseObjectPool

如果就存储接口来讲应该包括:数组、链表、键值对。

UML图如下:


而键值对的结构:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值