通用对象池

通用对象池GenericObjectPool_weixin_39407066的博客-CSDN博客

GenericObjectPool 是 Apache Commons Pool 提供的对象池,使用的时候需要调用 borrowObject 获取一个对象,使用完以后需要调用 returnObject 归还对象,或者调用 invalidateObject 将这个对象标记为不可再用。

GenericObjectPool 创建时,可以用有参构造函数进行初始化,通过GenericObjectPoolConfig 和PooledObjectFactory来进行参数的初始化和对象工厂类的引入。

PooledObjectFactory 需要重写的函数 makeObject、borrowObject 、validateObject、 destroyObject

  1. makeObject 创建对象的具体实现
  2. borrowObject 获取对象池中的对象简单而言就是去LinkedList中获取一个对象,如果不存在的话,要调用构造方法中第一个参数Factory工厂类的makeObject()方法去创建一个对象再获取,获取到对象后要调用validateObject方法判断该对象是否是可用的,如果是可用的才拿去使用。LinkedList容器减一。
  3. validateObject方法判断该对象是否是可用的。
  4. returnObject 先调用validateObject方法判断该对象是否是可用的,如果可用则归还到池中,LinkedList容器加一,如果是不可以的则则调用destroyObject方法进行销毁。
 
  1. @Override
  2. public PooledObject<T> makeObject() throws Exception {
  3. return new DefaultPooledObject<T>(T类型对象);
  4. }
  5.  
  6. @Override
  7. public void destroyObject(PooledObject<T> p) throws Exception {
  8. final T t= p.getObject();
  9. //t.xx
  10. }
  11.  
  12. @Override
  13. public boolean validateObject(PooledObject<T> p) {
  14. final T t= p.getObject();
  15. try {
  16. t.xx
  17. } catch (final Exception e) {
  18. return false;
  19. }
  20. }
  21.  
  22.  
  23.  
  24. 父类:
  25. @Override
  26. public PooledObject<T> makeObject() throws Exception {
  27. return wrap(create());
  28. }
  29. 子类:可以重新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.打开泄漏清理

设置了抛弃时间以后还需要打开泄漏清理才会生效。泄漏判断的开启可以通过两种方式:

  1. 从对象池中获取对象的时候进行清理 如果当前对象池中少于2个idle状态的对象或者 active数量>最大对象数-3 的时候,在borrow对象的时候启动泄漏清理。通过 AbandonedConfig.setRemoveAbandonedOnBorrow 为 true 进行开启。

  2. 启动定时任务进行清理 AbandonedConfig.setRemoveAbandonedOnMaintenance 设置为 true 以后,在维护任务运行的时候会进行泄漏对象的清理,可以通过 GenericObjectPool.setTimeBetweenEvictionRunsMillis 设置维护任务执行的时间间隔。一般5秒运行一次维护任务。

对象池 GenericObjectPool 配置参数详解_Huazie的博客-CSDN博客

巧用GenericObjectPool创建自定义对象池 (baidu.com)

 

posted @ 2023-08-11 16:18  CharyGao  阅读(62)  评论(0编辑  收藏  举报