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

来源:互联网 发布:海思 网络摄像机 sdk 编辑:程序博客网 时间:2024/05/23 15:42

参考:

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图如下:


而键值对的结构:







原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 25天的宝宝便秘怎么办 2个月宝宝便秘怎么办 猫拉绿色稀水怎么办 50天的宝宝便秘怎么办 人工喂养大便次数少怎么办 4个月宝宝肠炎怎么办? 三个月的宝宝拉肚子有奶瓣怎么办 吃米粉后不拉屎怎么办 宝宝拉绿色稀水怎么办 3个月宝宝肠胃炎怎么办 两个月婴儿拉水怎么办 3个月宝宝拉绿水怎么办 宝宝拉绿色的水怎么办 宝宝大便绿又水怎么办 8个月婴儿便秘怎么办 2个月婴儿便秘怎么办 四个月宝宝拉稀带有泡沫怎么办 六个月宝宝拉肚子怎么办拉水 婴儿拉的是沫怎么办 婴儿拉泡沫屎是怎么办 宝宝吃奶粉上火大便干燥怎么办 没满月的宝宝拉肚子怎么办 婴儿吃奶粉上火不大便怎么办 四个月宝宝拉沫怎么办 4个月小孩拉肚子怎么办 3个月的宝宝拉稀怎么办 宝宝没喝过奶粉怎么办 宝宝喝冰酸奶咳嗽了怎么办 7个月不爱喝奶怎么办 宝宝不认妈妈该怎么办 九个月宝宝不喝牛奶怎么办 吃羊肉和西瓜后怎么办 娃儿感冒了很咳怎么办 5岁娃儿经常感冒发烧怎么办 娃儿冷得发抖感冒怎么办 吃羊肉和茶后怎么办 宝宝胆汁酸高22怎么办 5个月发烧38度怎么办 28个月宝宝不愿把尿怎么办 16个月宝宝咳嗽怎么办 宝宝晚上不用纸尿裤要尿床怎么办