Java模块 -- Apache Commons Pool 对象池_简介

Apache Commons Pool 对象池

1. 对象池
a. 对象池就是以"空间换时间"的一种常用缓存机制,这里的"时间"特指创建时间。
b. 如果一种对象的创建过程非常耗时的话,那么请使用对象池。
c. 从内部原理简单的说,对象池技术就是将创建的对象放到一个容器中,用完之后不是销毁而是再放回该容器,让其他的对象调用。
d. 对象池中还涉及到一些高级的技术,比如过期销毁,被破坏时销毁,对象数超过池大小销毁,对象池中没有可用空闲对象时等待等等。


2. 为什么使用Commons pool 对象池技术?
a. 创建新的对象并初始化,可能会消耗很多时间。
b.在需要大量或者频繁生成这样的对象的时候,就可能会对性能造成一些不可忽略的影响。


3. 对象池技术解释
a.对象池的基本思路是:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频繁创建对象所造成的开销.
b. 用于充当保存对象的“容器”的对象,被称为“对象池”(Object Pool,或简称Pool)。
c. 并非所有对象都适合拿来池化――因为维护对象池也要造成一定开销。
  对生成时开销不大的对象进行池化,反而可能会出现“维护对象池的开销”大于“生成新对象的开销”,从而使性能降低的情况。
  但是对于生成时开销可观的对象,池化技术就是提高性能的有效策略了。

综上所述 :恰当地使用对象池化技术,可以有效地减少对象生成和初始化时的消耗,提高系统的运行效率。


详解:

a. PoolableObjectFactory : 用于管理被池化的对象的产生、激活、挂起、校验和销毁;
i. 创建 PoolableObjectFactory  
1) Pool组件利用PoolableObjectFactory来照看被池化的对象。

2) ObjectPool的实例在需要处理被池化的对象的产生、激活、挂起、校验和销毁工作时,
  就会调用跟它关联在一起的PoolableObjectFactory实例的相应方法来操作。

3) PoolableObjectFactory是在org.apache.commons.pool包中定义的一个接口。
  实际使用的时候需要利用这个接口的一个具体实现。
  Pool组件本身没有包含任何一种PoolableObjectFactory实现,需要根据情况自行创立。
b. ObjectPool
i. 用于管理要被池化的对象的借出和归还,并通知PoolableObjectFactory完成相应的工作;

c. ObjectPoolFactory
i. 用于大量生成相同类型和设置的ObjectPool。 


工厂类

import org.apache.commons.pool.PoolableObjectFactory;

//1.创建一个实现了PoolableObjectFactory接口的类。
/**
 * PoolableObjectFactory接口 : 池对象工厂
 * 		用来创建池对象,将不用的池对象进行钝化(passivateObject),
 * 		对要使用的池对象进行激活(activeObject),
 * 		对池对象进行验证(validateObject),
 * 		对有问题的池对象进行销毁(destroyObject)等工作。
 */

public class PoolableObjectFactorySample implements PoolableObjectFactory {

		private static int counter = 0;
		
		@Override
		//用于在必要时产生新的对象。
		public Object makeObject() throws Exception {
				Object obj = String.valueOf(counter++);
				System.out.println("Making Object " + obj);
				return obj;
		}

		@Override
		//用于将对象“激活”――设置为适合开始使用的状态。
		public void activateObject(Object obj) throws Exception {
				System.out.println("Activating Object : " + obj);
		}

		@Override
		//用于将对象“挂起”――设置为适合开始休眠的状态。
		public void passivateObject(Object obj) throws Exception {
				System.err.println("Passivating Object " + obj);

		}

		@Override
		//用于校验一个具体的对象是否仍然有效,已失效的对象会被自动交给destroyObject方法销毁
		public boolean validateObject(Object obj) {
				//以1/2的概率将对象判定为失效
				boolean result = (Math.random() > 0.5);
				System.err.println("Validating Object " + obj + " : " + result);
				return result;
		}

		@Override
		//用于销毁被validateObject判定为已失效的对象。
		public void destroyObject(Object obj) throws Exception {
				System.err.println("Destroying Object " + obj);
		}

}

测试调用类

import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool.Config;


/**
* @author CYX
* 
* GenericObjectPool : 租车公司
* 		作为租车公司,需要提供以下几个服务:
* 			1.租车
* 			2.收回
* 			3.买新车
* 			4.销毁
* 			5.定期检查
* 
* PooledObject : 租车公司的所有车辆
*		1.空闲可用的车辆
*		2.已借出的车辆
*		3.认为已丢弃的车辆
*
* BorrowObject : 租车
* 		1.世界那么大,一位年轻人想租辆车出去逛逛
* 		2.老板,先看看有没有空闲的车
* 		3.如果有,则将最近归还的车借出去,并标记为已借出(Active)
* 		     如果没有空闲的车了,就买辆,同时也标记为已借出(这是一家不差钱的公司)
* 		4.老板把标记好的车租给年轻人
* 
* ReturnObject : 还车
* 		1.世界那么大,年轻人终于逛完了,回来还车
* 		2.老板把车放回停车场,并把标记改为空闲状态(Idle),可以再被其他人租用。
* 
* 这 家公司不仅不差钱,它对车辆的安全还很负责,对于租出去的车,不管是从空闲车辆里取出的,还是新买回的,都会先检查一遍这车的好坏,
* 总不能坑了年轻人,如 果发现有问题,立马再换一辆。归还的时候,也会检查一遍,如果有问题,就扔掉(真土豪).
* 除此之外,公司还专门请了一位车辆安检员,定期对闲置了一段时间 的车辆进行安全检测(Evict Thread),一有问题也扔掉。
*
*
* 有借有还,看上去一切都很美好。
* 	然而现实里总有意外发生:年轻人借走车后,发现世界越逛越大,久久不愿回家。
* 	安检员定期检查时发现这车子都借出去大半年了,还没还回来,是不是丢了?
*  于是掏出手机,”啪“的按了一下,远程将车子熄了火,标记为报废车辆(Abandoned),当作报废处理了。
* 
*
* 
* Evict Thread(定期检查的安检人员)
* 1.对于已归还标记为空闲的车辆,安检员定期对它们抽查,如果超过一段时间没有使用,看看是否坏掉,坏了就及时作废掉(C2).
* 2.对于标记为已借出的对象,安检员定期检查时发现借出很久都未还,直接作废(D2)。
* 
*/
public class ObjectPool {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {

	Object obj = null;

	// 生成一个要用的PoolableObjectFactory类的实例。
	PoolableObjectFactorySample factory = new PoolableObjectFactorySample();
			
	Config conf = new Config();
	conf.maxActive=10;
	conf.whenExhaustedAction=1;
	
	GenericObjectPool pool = new GenericObjectPool(factory,conf);

	try {
			for (int i = 0; i < 10; i++) {
					System.out.println("== " + i + " ==");
					obj = pool.borrowObject(); // 需要从对象池中取出对象时,调用该对象池的Object borrowObject()方法。
					System.out.println(obj);
					pool.returnObject(obj); // 需要将对象放回对象池中时,调用该对象池的void returnObject(Object obj)方法。
			}
			obj = null; // 明确的设为null,作为对象已归还的标志.
	} catch (Exception e) {
			e.printStackTrace();
	} finally {
			try {
					if (obj != null) { // 避免一个对象二次归还
							pool.returnObject(obj);
					}
					 pool.close(); //当不再需要使用一个对象池时,调用该对象池的void close()方法,释放它所占据的资源。
			} catch (Exception e) {
					e.printStackTrace();
			}
	}
	}
}

对象池的配置

maxActive: 链接池中最大连接数,默认为8.
maxIdle: 链接池中最大空闲的连接数,默认为8.
minIdle: 连接池中最少空闲的连接数,默认为0.
maxWait: 当连接池资源耗尽时,调用者最大阻塞的时间,超时将跑出异常。单位,毫秒数;默认为-1.表示永不超时.
minEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲连接将可能会被移除。负值(-1)表示不移除。
softMinEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲链接将会被移除,且保留“minIdle”个空闲连接数。默认为-1.
numTestsPerEvictionRun: 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3.
testOnBorrow: 向调用者输出“链接”资源时,是否检测是有有效,如果无效则从连接池中移除,并尝试获取继续获取。默认为false。建议保持默认值.
testOnReturn:  向连接池“归还”链接时,是否检测“链接”对象的有效性。默认为false。建议保持默认值.
testWhileIdle:  向调用者输出“链接”对象时,是否检测它的空闲超时;默认为false。如果“链接”空闲超时,将会被移除。建议保持默认值.
timeBetweenEvictionRunsMillis:  “空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1.
 whenExhaustedAction: 当“连接池”中active数量达到阀值时,即“链接”资源耗尽时,连接池需要采取的手段, 默认为1:
 -> 0 : 抛出异常,
 -> 1 : 阻塞,直到有可用链接资源
 -> 2 : 强制创建新的链接资源
	这些属性均可以在org.apache.commons.pool.impl.GenericObjectPool.Config中进行设定。

#设置后进先出的池策略 
lifo=true 
#允许最大活动对象数 
maxActive=24 
#允许最大空闲对象数 
maxIdle=6 
#允许最大等待时间毫秒数 
maxWait=150000 
#被空闲对象回收器回收前在池中保持空闲状态的最小时间毫秒数 
minEvictableIdleTimeMillis=100000 
#允许最小空闲对象数 
minIdle=0 
#设定在进行后台对象清理时,每次检查对象数 
numTestsPerEvictionRun=1 
#指明是否在从池中取出对象前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个. 
testOnBorrow =false 
#指明是否在归还到池中前进行检验 
testOnReturn =false 
#指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除. 
testWhileIdle=false 
#在空闲连接回收器线程运行期间休眠的时间毫秒数. 如果设置为非正数,则不运行空闲连接回收器线程 
timeBetweenEvictionRunsMillis=120000 
#当池中对象用完时,请求新的对象所要执行的动作 
whenExhaustedAction=1


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值