java对象池commons-pool-1.6详解(三)

来源:互联网 发布:郭德纲才学 知乎 编辑:程序博客网 时间:2024/05/23 17:24

前面讲述了不带key的对象池,本文重点介绍另一种对象池——带key的,这种对象池在实际应用中更加广泛。例如:我们在rpc的系统中,需要对rpc对象进行池化提升其效率,但在实际环境中我们通常考虑ha,会对一个rpc服务在不同服务器上部署多个,这种情况下如果使用普通的对象池就会把所有服务器上部署的rcp服务对象放到一个池子中,不利于负载均衡,使用带有key的对象池可以很好做到负载均衡和池化对象。

一、重点接口介绍:

在Apache-commons-pool-1.6中,对带key的对象池也同样定义了三个顶级接口:KeyedObjectPool<k,v>、KeyedObjectPoolFactory<K, V>、KeyedPoolableObjectFactory<K, V>;和不带key的对象池那三个接口作用一样,其中KeyedObjectPoolKeyedObjectPoolFactory在功能上是一样的(都有三个不同的实现类),不同点仅在于使用上不同(后者通过工厂的方式使用),具体实例见后面;KeyedPoolableObjectFactory是池化对象接口,被池化的对象需要实现该接口

1)对象池接口:

KeyedObjectPool<k,v>接口用于管理要被池化对象的借出(borrowObject)、归还(returnObject)、失效移除(invalidateObject)、预加载(addObject)以及对象池的清空(clear、close)等,它通过PoolableObjectFactory来完成相应对象的各种操作。eyedObjectPoolFactory<K, V>接口是对KeyedObjectPool<k,v>的一个工厂化封装,用于生产KeyedObjectPool<k,v>接口。

2)池化对象接口:

eyedPoolableObjectFactory<K, V>接口用于管理被池化对象(被池化的对象需要实现该接口),主要功能包括对象的产生(makeObject),激活(activateObject),挂起(passivateObject),检验(validateObject)和销毁(destroyObject)等。

二、带key的对象池使用:

1、对象池:

和不带key的对象池一样,他们都统一遵循对象池的内部结构:idle区、abandom区、invalid区;同时也遵循一套对象池内部的驱逐、逐放、有效性探测等策略;在使用上也是先borrowObject,使用完毕后需要returnObject(不同点在于带key的对象池borrowObject的时候需要指定key,returnObject时也要指定key)。

2、池化对象:

和不带key的对象池一样,他们都遵循一套池化对象的状态、池化对象生命周期,以及池化对象的组织结构。

三、实现类:

KeyedObjectPool<k,v>对象池接口下面有两个实现类:GenericKeyedObjectPool、StackKeyedObjectPool

1、GenericKeyedObjectPool:(重点)

GenericKeyedObjectPool同GenericObjectPool一样,采用LIFO/FIF,池的默认行为是一个LIFO,这就意味着,当池中有空闲可用的对象时,调用borrowObject方法会返回最近(“后进”)的实例。如果LIFO策略在池中是false的,实例的返回按相反的顺序,-先进 - 先出。它利用一个org.apache.commons.collections.CursorableLinkedList对象来保存对象池里的对象。

1)这种对象池的特色是:

  • 可以设定最多能从池中借出多少个对象。
  • 可以设定池中最多能保存多少个对象。
  • 可以设定在池中已无对象可借的情况下,调用它的borrowObject方法时的行为,是等待、创建新的实例还是抛出异常。
  • 可以分别设定对象借出和还回时,是否进行有效性检查。
  • 可以设定是否使用一个单独的线程,对池内对象进行后台清理。
2)构造函数:

最简单的是GenericKeyedObjectPool(KeyedPoolableObjectFactory factory),仅仅指明要用的KeyedPoolableObjectFactory实例,其它参数则采用默认值;此外可以通过GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) 构造函数来构造复杂的配置,其中GenericKeyedObjectPool.Config可以设置:

  • int maxActive
  • int maxIdle
  • long maxWait
  • long minEvictableIdleTimeMillis
  • int numTestsPerEvictionRun
  • boolean testOnBorrow
  • boolean testOnReturn
  • boolean testWhileIdle
  • long timeBetweenEvictionRunsMillis
  • byte whenExhaustedAction

2、StackKeyedObjectPool

同StackObjectPool一样,在这里就不多列举了。

四、实例:

1)定义被池化的实例;

package cn.eud.nuc.pool.bean;public class MyBean {private Long id;private String name;private String other;public void abc(int inxtInt) throws InterruptedException {Thread.sleep(1000);System.out.println(this.toString());}public MyBean(Long id, String name, String other) {super();this.id = id;this.name = name;this.other = other;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getOther() {return other;}public void setOther(String other) {this.other = other;}@Overridepublic String toString() {return "MyBean [id=" + id + ", name=" + name + ", other=" + other + "]";}}
2)实现池化接口:

package cn.eud.nuc.pool.bean;import java.util.concurrent.ThreadLocalRandom;import org.apache.commons.pool.BaseKeyedPoolableObjectFactory;public class MyBeanKeyedPool extends BaseKeyedPoolableObjectFactory<String,MyBean>{private ThreadLocalRandom random = ThreadLocalRandom.current();@Overridepublic void destroyObject(String key,MyBean client) throws Exception {System.out.println("======================================================destroy...");}@Overridepublic boolean validateObject(String key,MyBean client) {return true;}@Overridepublic MyBean makeObject(String key) throws Exception {System.out.println("make...");long id = random.nextLong(10000000);return new MyBean(id,System.currentTimeMillis()+"_test",key);}}
说明:BaseKeyedPoolableObjectFactory抽象类实现了KeyedPoolableObjectFactory接口。

3)测试1:(使用GenericKeyedObjectPool接口)

package cn.eud.nuc.pool;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadLocalRandom;import org.apache.commons.pool.impl.GenericKeyedObjectPool;import cn.eud.nuc.pool.bean.MyBean;import cn.eud.nuc.pool.bean.MyBeanKeyedPool;public class TestKeyed {public static void main(String...strings) throws InterruptedException {MyBeanKeyedPool myBeanPool = new MyBeanKeyedPool();GenericKeyedObjectPool.Config poolConfig = new GenericKeyedObjectPool.Config();poolConfig.maxActive = 100;poolConfig.maxIdle = 1;//poolConfig.minIdle = 0;poolConfig.minEvictableIdleTimeMillis = 1000000000;poolConfig.timeBetweenEvictionRunsMillis = 10 * 2L;poolConfig.testOnBorrow=false;poolConfig.testOnReturn=true;poolConfig.testWhileIdle=true;poolConfig.lifo = false;//poolConfig.maxWait = 100000000;GenericKeyedObjectPool<String,MyBean> genericObjectPool = new GenericKeyedObjectPool<>(myBeanPool, poolConfig);//预热try {genericObjectPool.addObject("0");genericObjectPool.addObject("1");} catch (Exception e) {e.printStackTrace();}ExecutorService pool = Executors.newFixedThreadPool(200);for (int i=0;i<5000;i++) {pool.submit(new MyThread2(genericObjectPool));}//关闭/**pool.shutdown();try {genericObjectPool.close();} catch (Exception e) {e.printStackTrace();}*/}}class MyThread2 implements Runnable {private ThreadLocalRandom random = ThreadLocalRandom.current();private GenericKeyedObjectPool<String,MyBean> genericObjectPool;public MyThread2(GenericKeyedObjectPool<String,MyBean> genericObjectPool) {super();this.genericObjectPool = genericObjectPool;}@Overridepublic void run() {int nextInt = random.nextInt(2);MyBean borrowObject = null;boolean flag = true;String key = ""+nextInt;try {borrowObject = genericObjectPool.borrowObject(key);borrowObject.abc(nextInt);} catch (Exception e) {flag = false;e.printStackTrace();} finally {try {if (flag) {genericObjectPool.returnObject(key,borrowObject);} else {genericObjectPool.invalidateObject(key,borrowObject);}} catch (Exception e) {e.printStackTrace();}}}}

4)测试2:(使用GenericKeyedObjectPoolFactory接口)

package cn.eud.nuc.pool;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadLocalRandom;import org.apache.commons.pool.KeyedObjectPool;import org.apache.commons.pool.impl.GenericKeyedObjectPool;import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;import cn.eud.nuc.pool.bean.MyBean;import cn.eud.nuc.pool.bean.MyBeanKeyedPool;public class TestKeyed2 {public static void main(String...strings) throws InterruptedException {MyBeanKeyedPool myBeanPool = new MyBeanKeyedPool();GenericKeyedObjectPool.Config poolConfig = new GenericKeyedObjectPool.Config();poolConfig.maxActive = 100;poolConfig.maxIdle = 1;//poolConfig.minIdle = 0;poolConfig.minEvictableIdleTimeMillis = 1000000000;poolConfig.timeBetweenEvictionRunsMillis = 10 * 2L;poolConfig.testOnBorrow=false;poolConfig.testOnReturn=true;poolConfig.testWhileIdle=true;poolConfig.lifo = false;//poolConfig.maxWait = 100000000;GenericKeyedObjectPoolFactory<String,MyBean> genericObjectPoolFactory = new GenericKeyedObjectPoolFactory<>(myBeanPool, poolConfig);KeyedObjectPool<String, MyBean> createPool = genericObjectPoolFactory.createPool();//预热try {createPool.addObject("0");createPool.addObject("1");} catch (Exception e) {e.printStackTrace();}ExecutorService pool = Executors.newFixedThreadPool(200);for (int i=0;i<5000;i++) {pool.submit(new MyThread3(createPool));}//关闭/*pool.shutdown();try {createPool.close();} catch (Exception e) {e.printStackTrace();}*/}}class MyThread3 implements Runnable {private ThreadLocalRandom random = ThreadLocalRandom.current();private KeyedObjectPool<String, MyBean> createPool;public MyThread3(KeyedObjectPool<String, MyBean> createPool) {super();this.createPool = createPool;}@Overridepublic void run() {int nextInt = random.nextInt(2);MyBean borrowObject = null;boolean flag = true;String key = ""+nextInt;try {borrowObject = createPool.borrowObject(key);borrowObject.abc(nextInt);} catch (Exception e) {flag = false;e.printStackTrace();} finally {try {if (flag) {createPool.returnObject(key,borrowObject);} else {createPool.invalidateObject(key,borrowObject);}} catch (Exception e) {e.printStackTrace();}}}}

参考:

http://blog.csdn.net/bhy5683/article/details/8776498