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

来源:互联网 发布:蚌埠市农村金融数据 编辑:程序博客网 时间:2024/05/29 05:54

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


阅读全文
0 0
原创粉丝点击