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的对象池那三个接口作用一样,其中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;
	}
	
	@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();
			}
		}
	}
}

参考:

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赶路人儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值