java 对象池 apache_Apache Commons-pool实现对象池(包括带key对象池)

public class TestPoolableFactory implementsPoolableObjectFactory {//重新初始化实例返回池

@Overridepublic void activateObject(Object arg0) throwsException {

((BaseObject)arg0).setActive(true);

}//销毁被破坏的实例

@Overridepublic void destroyObject(Object arg0) throwsException {

arg0= null;

}//创建一个实例到对象池

@Overridepublic Object makeObject() throwsException {

BaseObject bo= newBaseObject();returnbo;

}//取消初始化实例返回到空闲对象池

@Overridepublic void passivateObject(Object arg0) throwsException {

((BaseObject)arg0).setActive(false);

}//验证该实例是否安全

@Overridepublic booleanvalidateObject(Object arg0) {if(((BaseObject)arg0).isActive())return true;else

return false;

}

}

这是带key的工厂类TestKeyPoolableFactory.java

public class TestKeyPoolableFactory implements KeyedPoolableObjectFactory{//重新初始化实例返回池

@Overridepublic void activateObject(String arg0, BaseObject arg1) throwsException {

((BaseObject)arg1).setActive(true);

}//销毁被破坏的实例

@Overridepublic void destroyObject(String arg0, BaseObject arg1) throwsException {

arg1= null;

}//创建一个实例到对象池

@Overridepublic BaseObject makeObject(String arg0) throwsException {//这里从数据库里查询出使用次数最少的配置

BaseObject bo = newBaseObject();

bo.setNum(0);returnbo;

}//取消初始化实例返回到空闲对象池

@Overridepublic void passivateObject(String arg0, BaseObject arg1) throwsException {

((BaseObject)arg1).setActive(false);

}//验证该实例是否安全 true:正在使用

@Overridepublic booleanvalidateObject(String arg0, BaseObject arg1) {//这里可以判断实例状态是否可用

if(((BaseObject)arg1).isActive())return true;else

return false;

}

}

3)测试main方法

不带key的main方法类PoolTest.java

public classPoolTest {public static voidmain(String[] args) {

BaseObject bo= null;

PoolableObjectFactory factory= newTestPoolableFactory();

GenericObjectPool pool= newGenericObjectPool(factory);//这里两种池都可以,区别下文会提到//ObjectPool pool = new StackObjectPool(factory);

try{for(int i = 0; i < 5; i++) {

System.out.println("\n==========="+i+"===========");

System.out.println("池中处于闲置状态的实例pool.getNumIdle():"+pool.getNumIdle());//从池里取一个对象,新创建makeObject或将以前闲置的对象取出来

bo =(BaseObject)pool.borrowObject();

System.out.println("bo:"+bo);

System.out.println("池中所有在用实例数量pool.getNumActive():"+pool.getNumActive());if((i%2) == 0) {//用完之后归还对象

pool.returnObject(bo);

System.out.println("归还对象!!!!");

}

}

}catch(Exception e) {

e.printStackTrace();

}finally{try{if(bo != null) {

pool.returnObject(bo);

}//关闭池

pool.close();

}catch(Exception e) {

e.printStackTrace();

}

}

}

}

输出结果:

===========0===========池中处于闲置状态的实例pool.getNumIdle():0

new BaseObject!!!!!bo:common.keypool.BaseObject@1fdc96c

池中所有在用实例数量pool.getNumActive():1归还对象!!!!===========1===========池中处于闲置状态的实例pool.getNumIdle():1bo:common.keypool.BaseObject@1fdc96c

池中所有在用实例数量pool.getNumActive():1

===========2===========池中处于闲置状态的实例pool.getNumIdle():0

new BaseObject!!!!!bo:common.keypool.BaseObject@124bbbf

池中所有在用实例数量pool.getNumActive():2归还对象!!!!===========3===========池中处于闲置状态的实例pool.getNumIdle():1bo:common.keypool.BaseObject@124bbbf

池中所有在用实例数量pool.getNumActive():2

===========4===========池中处于闲置状态的实例pool.getNumIdle():0

new BaseObject!!!!!bo:common.keypool.BaseObject@a20892

池中所有在用实例数量pool.getNumActive():3归还对象!!!!

这里的池声明用ObjectPool或者GenericObjectPool的区别在于:

ObjectPool这种对象池的特点是:

可以为对象池指定一个初始的参考大小(当空间不够时会自动增长)。

在对象池已空的时候,调用它的borrowObject方法,会自动返回新创建的实例。

可以为对象池指定一个可保存的对象数目的上限。达到这个上限之后,再向池里送回的对象会被自动送去回收。

GenericObjectPool这种对象池的特色是:

可以设定最多能从池中借出多少个对象。

可以设定池中最多能保存多少个对象。

可以设定在池中已无对象可借的情况下,调用它的borrowObject方法时的行为,是等待、创建新的实例还是抛出异常。

可以分别设定对象借出和还回时,是否进行有效性检查。

可以设定是否使用一个单独的线程,对池内对象进行后台清理。

……

这些参数可以通过一个Config类来管理,然后通过GenericObjectPool的setConfig(Config conf)方法来设置自定义的Config类。下面附上setConfig方法源码,就知道Config类需要哪些参数了:

源码GenericKeyedObjectPool.java类内部的setConfig方法

/*** Sets the configuration.

*@paramconf the new configuration to use.

*@seeGenericKeyedObjectPool.Config*/

public synchronized voidsetConfig(GenericKeyedObjectPool.Config conf) {

setMaxIdle(conf.maxIdle);

setMaxActive(conf.maxActive);

setMaxTotal(conf.maxTotal);

setMinIdle(conf.minIdle);

setMaxWait(conf.maxWait);

setWhenExhaustedAction(conf.whenExhaustedAction);

setTestOnBorrow(conf.testOnBorrow);

setTestOnReturn(conf.testOnReturn);

setTestWhileIdle(conf.testWhileIdle);

setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);

setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);

setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);

}

源码GenericObjectPool.java类内部的setConfig方法

/*** Sets my configuration.

*

*@paramconf configuration to use.

*@seeGenericObjectPool.Config*/

public voidsetConfig(GenericObjectPool.Config conf) {synchronized (this) {

setMaxIdle(conf.maxIdle);

setMinIdle(conf.minIdle);

setMaxActive(conf.maxActive);

setMaxWait(conf.maxWait);

setWhenExhaustedAction(conf.whenExhaustedAction);

setTestOnBorrow(conf.testOnBorrow);

setTestOnReturn(conf.testOnReturn);

setTestWhileIdle(conf.testWhileIdle);

setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);

setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);

setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);

setSoftMinEvictableIdleTimeMillis(conf.softMinEvictableIdleTimeMillis);

setLifo(conf.lifo);

}

allocate();

}

1.      参数maxActive指明能从池中借出的对象的最大数目。如果这个值不是正数,表示没有限制。

2.      参数whenExhaustedA ction指定在池中借出对象的数目已达极限的情况下,调用它的borrowObject方法时的行为。可以选用的值有:

GenericObjectPool.WHEN_EXHAUSTED_BLOCK,表示等待;

GenericObjectPool.WHEN_EXHAUSTED_GROW,表示创建新的实例(不过这就使maxActive参数失去了意义);

GenericObjectPool.WHEN_EXHAUSTED_FAIL,表示抛出一个java.util.NoSuchElementException异常。

3.      参数maxWait指明若在对象池空时调用borrowObject方法的行为被设定成等待,最多等待多少毫秒。如果等待时间超过了这个数值,则会抛出一个java.util.NoSuchElementException异常。如果这个值不是正数,表示无限期等待。

4.      参数testOnBorrow设定在借出对象时是否进行有效性检查。

5.      参数testOnBorrow设定在还回对象时是否进行有效性检查。

6.      参数timeBetweenEvictionRunsMillis,设定间隔每过多少毫秒进行一次后台对象清理的行动。如果这个值不是正数,则实际上不会进行后台对象清理。

7.      参数minEvictableIdleTimeMillis,设定在进行后台对象清理时,视休眠时间超过了多少毫秒的对象为过期。过期的对象将被回收。如果这个值不是正数,那么对休眠时间没有特别的约束。

8.      参数testWhileIdle,则设定在进行后台对象清理时,是否还对没有过期的池内对象进行有效性检查。不能通过有效性检查的对象也将被回收。

9.      参数lifo,池对象的放入和取出默认是后进先出的原则,默认是true,代表后进后出,设置为false代表先进先出。

带key的main方法类KeyPoolTest.java

public classKeyPoolTest {public static voidmain(String[] args) {

BaseObject bo= null;

BaseObject bo1= null;

BaseObject bo2= null;

KeyedPoolableObjectFactory keyFactory = newTestKeyPoolableFactory();

GenericKeyedObjectPool keyPool = new GenericKeyedObjectPool(keyFactory);//keyPool.setLifo(false);

try{//这里添加池对象,只需要传入key就会默认调用makeObject()方法创建一个对象

keyPool.addObject("一级");

keyPool.addObject("二级");//这里注释掉,不初始创建这个键的池对象//keyPool.addObject("三级");

System.out.println("池中处于闲置状态的实例pool.getNumIdle():"+keyPool.getNumIdle());for (int i = 0; i < 5; i++) {//从池里取对象

bo = keyPool.borrowObject("一级");

bo.setNum(bo.getNum()+1);

System.out.println("一级"+i+"-------"+bo+"-------"+bo.getNum());

bo1= keyPool.borrowObject("二级");

bo1.setNum(bo1.getNum()+1);

System.out.println("二级"+i+"-------"+bo1+"-------"+bo1.getNum());//上边注释掉的那行代码,这里取对象的时候如果没有闲置对象,也会默认去创建一个key="三级"的池对象

bo2 = keyPool.borrowObject("三级");

bo2.setNum(bo2.getNum()+1);

System.out.println("三级"+i+"-------"+bo2+"-------"+bo2.getNum());if(i<3) {//用完之后归还对象

keyPool.returnObject("一级", bo);

keyPool.returnObject("二级", bo1);

keyPool.returnObject("三级", bo2);

System.out.println("归还对象!!!");

}

}//当前池里的实例数量

System.out.println("池中所有在用实例pool.getNumActive():"+keyPool.getNumActive());//当前池里的处于闲置状态的实例

System.out.println("池中处于闲置状态的实例pool.getNumIdle():"+keyPool.getNumIdle());

}catch(Exception e) {

e.printStackTrace();

}//这里就不写finally了,偷懒了,这里应该关闭池的

}

}

输出结果:

new BaseObject!!!!!

new BaseObject!!!!!池中处于闲置状态的实例pool.getNumIdle():2一级0-------common.keypool.BaseObject@158b649-------1二级0-------common.keypool.BaseObject@127734f-------1

new BaseObject!!!!!三级0-------common.keypool.BaseObject@1037c71-------1归还对象!!!

一级1-------common.keypool.BaseObject@158b649-------2二级1-------common.keypool.BaseObject@127734f-------2三级1-------common.keypool.BaseObject@1037c71-------2归还对象!!!

一级2-------common.keypool.BaseObject@158b649-------3二级2-------common.keypool.BaseObject@127734f-------3三级2-------common.keypool.BaseObject@1037c71-------3归还对象!!!

一级3-------common.keypool.BaseObject@158b649-------4二级3-------common.keypool.BaseObject@127734f-------4三级3-------common.keypool.BaseObject@1037c71-------4

new BaseObject!!!!!一级4-------common.keypool.BaseObject@1df073d-------1

new BaseObject!!!!!二级4-------common.keypool.BaseObject@1546e25-------1

new BaseObject!!!!!三级4-------common.keypool.BaseObject@b66cc-------1池中所有在用实例pool.getNumActive():6池中处于闲置状态的实例pool.getNumIdle():0

通过输出结果可以看出:

1.对象取出之后可以对对象进行更改,再放回池里这个更改是保留的。

2.池对象的放入和取出默认是后进先出的原则,可以通过池pool的setLifo(boolean lifo)方法设置,默认是true,代表后进先出,设置为false代表先进先出。如果为了池对象使用均衡,推荐使用false。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值