1.背景
创建新的对象并初始化的操作,可能会消耗很多的时间。在这种对象的初始化工作包含了一些费时的操作(如建立网络连接,数据库连接)的时候,尤其是这样。在需要大量生成这样的对象的时候,就可能会对性能造成一些不可忽略的影响。
要缓解这个问题,除了选用更好的硬件和更棒的虚拟机以外,适当地采用一些能够减少对象创建次数的编码技巧,也是一种有效的对策。对象池化技术(Object Pooling)就是这方面的著名技巧.
1.1池化技术
对象池化的基本思路是:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频繁创建对象所造成的开销。用于充当保存对象的“容器”的对象,被称为“对象池”(Object Pool,或简称Pool)。
1.2使用方式
对于没有状态的对象(例如String),在重复使用之前,无需进行任何处理;对于有状态的对象(例如StringBuffer),在重复使用之前,就需要把它们恢复到等同于刚刚生成时的状态。由于条件的限制,恢复某个对象的状态的操作不可能实现了的话,就得把这个对象抛弃,改用新创建的实例了。
1.3利与弊,使用场景
利:重复利用,减小生成对象的开销
弊:维护对象池的开销
使用场景:
对于生成时开销可观的对象,池化技术就是提高性能的有效策略了。
一般情况下,不宜池化的对象的范围可能会更大。不过,对于像网络和数据库连接这类重量级的对象来说,目前还是有池化的必要。
2.源码阅读
2.1说明
下面源码以commons-pool2版本2.2为例
2.2概念
池对象工厂(PooledObjectFactory ):
用来创建池对象, 将不用的池对象进行钝化(passivateObject), 对要使用的池对象进行激活(activeObject), 对池对象进行验证(validateObject), 对有问题的池对象进行销毁(destroyObject)等工作
池对象(PooledObject)
即池中的instance,主要对原本的instance类型进行了一层wrapper,来获取诸如状态,生命周期的信息
对象池(ObjectPool)
管理pool中对象的"借"与"还",获取active以及idle对象的数量等
2.3主要类介绍
PooledObjectFactory
用来管理ObjectPool里面的instance的生命周期
每个instance就是PooledObject
[官网](https://commons.apache.org/proper/commons-pool/api-2.2/org/apache/commons/pool2/PooledObjectFactory.html)
//创建新的实例,返回PooledObject对象
PooledObject makeObject() throws Exception;
//在pool借出对象前,需要将其激活,做一些标记以及清空的操作
void activateObject(PooledObject p) throws Exception;
/*
1.在pool借出对象前,在activate状态时验证是否有效
2.在对象被还给pool的时候,验证是否有效
*/
boolean validateObject(PooledObject p);
//在对象被还给pool的时候,进行钝化操作
void passivateObject(PooledObject p) throws Exception;
//当实例从pool中丢掉时使用,一般是被验证无效或者是特殊的实现考虑,和对象的状态并没有关系
void destroyObject(PooledObject p) throws Exception;
PooledObject
进行了wrap进而对状态(PooledObjectState)进行跟踪,以及对各种时间,次数的记录
稍微介绍几个函数
//获取wrap之前的object
T getObject();
常见实现类是DefaultPooledObject以及PooledSoftReference
具体的状态变化详见下一节
ObjectPool
函数介绍如下
//从pool中借出对象
T borrowObject() throws Exception, NoSuchElementException, IllegalStateException;
//把对象还给pool
void returnObject(T obj) throws Exception;
//把对象无效化
void invalidateObject(T obj) throws Exception;
//利用PooledObjectFactory生成对象,钝化并且加入到pool的idle队列里面去,一般用于预加载
void addObject() throws Exception, IllegalStateException, UnsupportedOperationException;
int getNumIdle();
int getNumActive();
//把pool中处于idle状态的object都清空掉,释放资源
void clear() throws Exception, UnsupportedOperationException;
//关闭对象池,释放资源
void close();
3.思考
池化技术的应用场景
池对象,池对象工厂以及对象池的关系
对象池中对象的借与还
不论借与换,对象对应的poolObject还是存在objectPool里面的
只不过进行一下状态的改变,队列的改变(active<->idle)等
并不是说从队列
ObjectPool#invalidateObject什么时候管用?
4.应用
dbcp,jedis
好奇为什么httpclient的PoolingHttpClientConnectionManager不用这个
5.refer
http://www.cnblogs.com/shipengzhi/archive/2011/06/02/2068565.html
http://www.cnblogs.com/shipengzhi/archive/2011/06/02/2068628.html
(下面两篇是官网以及翻译)
http://commons.apache.org/proper/commons-pool/index.html
http://ifeve.com/apache-commons-pool/
(下面是概念介绍)
https://my.oschina.net/xinxingegeya/blog/391560
(各种图以及状态的介绍)
http://aofengblog.blog.163.com/blog/static/6317021201463075826473/
(比较详细的源码解析)
http://www.jianshu.com/p/b49452fb3a67
(demo)
http://blog.csdn.net/ouyang111222/article/details/50949556
http://blog.csdn.net/xlxxcc/article/details/52402931