通用对象池
通用对象池GenericObjectPool_weixin_39407066的博客-CSDN博客
GenericObjectPool 是 Apache Commons Pool 提供的对象池,使用的时候需要调用 borrowObject 获取一个对象,使用完以后需要调用 returnObject 归还对象,或者调用 invalidateObject 将这个对象标记为不可再用。
GenericObjectPool 创建时,可以用有参构造函数进行初始化,通过GenericObjectPoolConfig 和PooledObjectFactory来进行参数的初始化和对象工厂类的引入。
PooledObjectFactory 需要重写的函数 makeObject、borrowObject 、validateObject、 destroyObject
- makeObject 创建对象的具体实现
- borrowObject 获取对象池中的对象简单而言就是去LinkedList中获取一个对象,如果不存在的话,要调用构造方法中第一个参数Factory工厂类的makeObject()方法去创建一个对象再获取,获取到对象后要调用validateObject方法判断该对象是否是可用的,如果是可用的才拿去使用。LinkedList容器减一。
- validateObject方法判断该对象是否是可用的。
- returnObject 先调用validateObject方法判断该对象是否是可用的,如果可用则归还到池中,LinkedList容器加一,如果是不可以的则则调用destroyObject方法进行销毁。
-
-
public PooledObject<T> makeObject() throws Exception {
-
return new DefaultPooledObject<T>(T类型对象);
-
}
-
-
-
public void destroyObject(PooledObject<T> p) throws Exception {
-
final T t= p.getObject();
-
//t.xx
-
}
-
-
-
public boolean validateObject(PooledObject<T> p) {
-
final T t= p.getObject();
-
try {
-
t.xx
-
} catch (final Exception e) {
-
return false;
-
}
-
}
-
-
-
-
父类:
-
-
public PooledObject<T> makeObject() throws Exception {
-
return wrap(create());
-
}
-
子类:可以重新creat方法和wrap方法,或者直接像上面那样重写
GenericObjectPoolConfig 参数设置
- maxTotal
最大连接数,默认值 DEFAULT_MAX_TOTAL = 8 - maxIdle
最大空闲连接数, 默认值 DEFAULT_MAX_IDLE = 8 - minIdle
最小空闲连接数, 默认值 DEFAULT_MIN_IDLE = 0 - testOnBorrow 在从对象池获取对象时是否检测对象有效(true : 是) , 配置true会降低性能;默认值 DEFAULT_TEST_ON_BORROW = false
- maxWaitMillis 当连接池资源用尽后,调用者获取连接时的最大等待时间(单位 :毫秒);默认值 DEFAULT_MAX_WAIT_MILLIS = -1L, 永不超时。
- lifo提供了后进先出(LIFO)与先进先出(FIFO)两种行为模式的池;默认 DEFAULT_LIFO = true, 当池中有空闲可用的对象时,调用borrowObject方法会返回最近(后进)的实例。(默认)
- fairness当从池中获取资源或者将资源还回池中时,是否使用;java.util.concurrent.locks.ReentrantLock.ReentrantLock 的公平锁机制。默认DEFAULT_FAIRNESS = false(默认)
- blockWhenExhausted当这个值为true的时候,maxWaitMillis参数才能生效。为false的时候,当连接池没资源,则立马抛异常。默认为true.
- testOnReturn 默认值 false; 设置为 true 时,当将资源返还个资源池时候,调用factory.validateObject()方法,验证资源的有效性,如果无效,则调用 factory.destroyObject()方法.
AbandonedConfig
GenericObjectPool可以通过setAbandonedConfig()方法来设置AbandonedConfig对象用来进行设置自动清理逻辑,
- removeAbandonedOnBorrow :如果设置为true,就意味着,在borrowObject方法中(从对象池中申请对象的时候)就可以进行遗弃对象的相关清理逻辑。 * (当然是否能触发清理,还受限于其他条件)
- removeAbandonedOnMaintenance :对象池本省可以通过GenericObjectPoolConfig配置后台异步清理任务,但是后台清理任务的主要职责是关注空闲(状态为空闲)对象的检测和清理。 * 如果removeAbandonedOnMaintenance设置为true,就意味着,在对象池的异步清理任务中,也可以进行遗弃(状态为活跃)对象的相关清理。
- removeAbandonedTimeout :这个时间,默认300s。如果对象池的一个对象被占用了超过300s还没有被释放,就认为是被调用方遗弃了。
- logAbandoned :如果处理发了遗弃对象的回收和清理,是否要打印该对象的调用堆栈。 * 生产环境十分不建议设为true,会很消耗性能
- logWriter :这是一个日志输出器,用来定义调用堆栈日志的输出行为(输出到控制台、文件等)。默认输出到控制台。 * 如果logAbandoned为false,就不会有输出行为。
- useUsageTracking :这个UsageTracking从名字上来直观翻译,叫做使用追踪,指的就是池中对象的使用追踪。UsageTracking也是一个接口,GenericObjectPool实现了该接口。什么叫使用? *就是只要是调用了池中对象的任何方法,就算使用了池中对象。 什么叫追踪? *就是在池中某个对象的任何一个方法被调用时,都会创建一个调用堆栈快照。 logAbandoned为true时,useUsageTracking也为true时,那么回收被遗弃的对象时,就会打印该对象最后一次的调用堆栈信息了。 如果useUsageTracking为true,即便是logAbandoned为false,那么每次对象的方法调用,一样还是会创建调用堆栈对象。只不过最终被回收时不会打印输出。 生产环境该属性也不建议设置为true。
实际应用中由于程序实现的问题,可能造成在一些极端的情况下出现 borrowObject/invalidateObject 没有被调用导致的泄漏问题。对象泄漏会导致对象池中的对象数量一直上升,达到设置的上限以后再调用 borrowObject 就会永远等待或者抛出 java.util.NoSuchElementException: Timeout waiting for idle object
异常。
设置自动清理
1.设置抛弃时间
GenericObjectPool判断一个对象是否泄漏是根据对象最后一次使用或者最后一次borrow的时间进行判断的,如果超出了预设的值就会被认为是一个泄漏的对象被清理掉(PooledObjectFactory.destroyObject在这一过程中会被调用)。抛弃时间可以通过 AbandonedConfig.setRemoveAbandonedTimeout 进行设置,时间单位是秒。
2.打开泄漏清理
设置了抛弃时间以后还需要打开泄漏清理才会生效。泄漏判断的开启可以通过两种方式:
-
从对象池中获取对象的时候进行清理 如果当前对象池中少于2个idle状态的对象或者 active数量>最大对象数-3 的时候,在borrow对象的时候启动泄漏清理。通过 AbandonedConfig.setRemoveAbandonedOnBorrow 为 true 进行开启。
-
启动定时任务进行清理 AbandonedConfig.setRemoveAbandonedOnMaintenance 设置为 true 以后,在维护任务运行的时候会进行泄漏对象的清理,可以通过 GenericObjectPool.setTimeBetweenEvictionRunsMillis 设置维护任务执行的时间间隔。一般5秒运行一次维护任务。
对象池 GenericObjectPool 配置参数详解_Huazie的博客-CSDN博客
巧用GenericObjectPool创建自定义对象池 (baidu.com)