0
点赞
收藏
分享

微信扫一扫

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

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

一、重点接口介绍:

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

@Override
public 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();



@Override
public void destroyObject(String key,MyBean client) throws Exception {
System.out.println("======================================================destroy...");
}


@Override
public boolean validateObject(String key,MyBean client) {
return true;
}

@Override
public 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;
}

@Override
public 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;
}

@Override
public 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();
}
}
}
}




举报

相关推荐

0 条评论