基于Apache Common-pool2理解连接池

基于Apache Common-pool2理解连接池

目的

  • 理解连接池的参数设置

文档介绍

PooledObjectState

事件 说明
IDLE 在队列中,但是为使用
ALLOCATED 正在使用
EVICTION 在队列中,但是正在被测试,可能清除
EVICTION_RETURN_TO_HEAD 不在队列中,目前正在测试可能的驱逐。在测试时试图借用该对象,该对象被删除从队列中。它应该返回到队列的头部一次,驱逐测试完成。
VALIDATION 在队列中,当前正在被校验
VALIDATION_PREALLOCATED 不在队列中,当前正在验证。这东西是借的正在进行验证,由于配置了testOnBorrow,所以删除了它,从队列中预先分配。应该在验证之后分配它
VALIDATION_RETURN_TO_HEAD 不在队列中,当前正在验证。试图借用对象是在之前进行驱逐测试时制作的,该测试将其移除队列。验证之后,它应该返回到队列的头部完成
INVALID 无效的,维护失败和将要被摧毁的对象
ABANDONED 废弃的
RETURNING 返回到池子中

java代码实现

代码实现
  • StringPoolObject.java
package com;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

public class StringPoolObject extends BasePooledObjectFactory<StringBuffer> {

    @Override
    public StringBuffer create() {
        System.out.println("创造了一个object");
        return new StringBuffer();
    }

    @Override
    public PooledObject<StringBuffer> wrap(StringBuffer obj) {
        DefaultPooledObject<StringBuffer> stringBufferDefaultPooledObject = new DefaultPooledObject<>(obj);
        System.out.println("wrap状态为-->"+stringBufferDefaultPooledObject.getState());
        return stringBufferDefaultPooledObject;
    }

    @Override
    public void passivateObject(PooledObject<StringBuffer> p) throws Exception {
        System.out.println("passivateObject状态为-->"+p.getState());
        super.passivateObject(p);
    }
}
  • MyStringUtils.java
package com;

import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;

import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

public class MyStringUtils {
    private ObjectPool<StringBuffer> objectPool;
    private AtomicInteger count;

    public MyStringUtils(ObjectPool<StringBuffer> objectPool) {
        this.objectPool = objectPool;
        count = new AtomicInteger();
    }

    public StringBuffer read() throws Exception {
        return objectPool.borrowObject();
    }

    public String write(StringBuffer write) throws Exception {
        Random random = new Random();
        int randomValue = random.nextInt(300);
        int order = count.addAndGet(1);
        StringBuffer append = write.append("第几个写的:").append(order).append("-->").append("写了什么:").append(randomValue);
        objectPool.returnObject(write);
        return append.toString();
    }

    public static void main(String[] args) throws Exception {
        PooledObjectFactory pooledObjectFactory = new StringPoolObject();
        ObjectPool objectPool = new GenericObjectPool(pooledObjectFactory);
        MyStringUtils myStringUtils = new MyStringUtils(objectPool);

        StringBuffer read = myStringUtils.read();

        myStringUtils.write(read);
        StringBuffer data = myStringUtils.read();
        System.out.println("数据是-->" + data.toString());
    }
}

输出
创造了一个Object
wrap状态为-->IDLE
passivateObject状态为-->RETURNING
数据是-->第几个写的:1-->写了什么:240

接口

PooledObjectFactor
作用
  • 提供poolObject的工厂,顶层的抽象类是BasePooledObjectFactory,复写create和wrap方法
代码
//连接池的工厂,通过makeObject返回连接池的包装类
//activateObject激活连接对象
//passivateObject钝化连接对象
//validateObject校验对象
//destroyObject摧毁对象
public interface PooledObjectFactory<T> {
    //返回连接池对象的包装器
    PooledObject<T> makeObject();
    void activateObject(PooledObject<T> obj);
    void passivateObject(PooledObject<T> obj);
    boolean validateObject(PooledObject<T> obj);
    void destroyObject(PooledObject<T> obj);
}
PooledObject
作用
  • 提供对象的包装类,封装了状态变更的方法,默认实现类是DefaultPooledObject
代码
//这个接口是连接池的包装类接口,用于管理连接池的状态
public interface PooledObject<T> extends Comparable<PooledObject<T>> {
    //返回连接池对象
    T getObject();
    //返回连接池创建时间。
    long getCreateTime();
    //返回连接的上次活动时间
    long getActiveTimeMillis();
    //该对象被调用的次数
    default long getBorrowedCount() {
        return -1;
    }
    //该对象空闲多少时间
    long getIdleTimeMillis();
    //最后一次被包装对象的时间
    long getLastBorrowTime();
    //上一次包装对象返回的时间
    long getLastReturnTime();
    //最新的使用时间
    long getLastUsedTime();
    //尝试将池对象置于PooledObjectState.EVICTION状态
    boolean startEvictionTest();
    //被叫通知对象驱逐测试已经结束 目前没有使用,参数: 空闲队列
    boolean endEvictionTest(Deque<PooledObject<T>> idleQueue);
    //分配该对象,如果源状态为PooledObjectState.IDLE空闲状态则返回true,
    //同时将状态改为PooledObjectState.ALLOCATED,该状态表明对象正在被使用
    boolean allocate();
    //取消分配对象并空闲 在当前设置它ALLOCATED。
    boolean deallocate();
    //设置是否记录对象使用的堆栈信息,可用于池泄漏时问题追溯
    void setLogAbandoned(boolean logAbandoned);
    /** 根据是否需要完全详细的堆栈跟踪配置堆栈跟踪生成策略。
        当设置为false时,被放弃的日志可能只包含调用者类信息,而不包含方法名、行
        数字,以及完整堆栈跟踪中可用的其他正常元数据。*/
    default void setRequireFullStackTrace(boolean requireFullStackTrace) {
        // noop
    }
    //将当前堆栈跟踪记录为上次使用对象的时间。
    void use();
    //打印借用此池对象的代码的堆栈跟踪以及最后一个代码的堆栈跟踪,以将此对象(如果可用)用于提供的编写器。
    void printStackTrace(PrintWriter writer);
    //返回此对象的状态。
    PooledObjectState getState();
    //将池化对象标记为已放弃。
    void markAbandoned();
    //将对象标记为返回池。
    void markReturning();
        @Override
    int compareTo(PooledObject<T> other);

    @Override
    boolean equals(Object obj);

    @Override
    int hashCode();
    
    @Override
    String toString();
}
ObjectPool
作用
  • 提供类使从池对象中使用方法,实现类是GenericObjectPool
代码
public interface ObjectPool<T> extends Closeable {
    //借用对象idle -> 
    T borrowObject() throws Exception, NoSuchElementException,
            IllegalStateException;
    //返回对象
    void returnObject(T obj) throws Exception;
    //使对象无效
    void invalidateObject(T obj) throws Exception;
    //添加对象
    void addObject() throws Exception, IllegalStateException,
            UnsupportedOperationException;
    //获得空闲数量
    int getNumIdle();
    //获得活动数量
    int getNumActive();
    //清除
    void clear() throws Exception, UnsupportedOperationException;
    //关闭
    void close();
}

实现类分析

DefaultPooledObject
方法 功能 状态变更
allocate 分配对象 IDLE -> ALLOCATED
deallocate 释放这对象 ALLOCATED -> IDLE
invalidate 无效对象 * -> INVALID
startEvictionTest 无效对象 IDLE -> EVICTION
endEvictionTest 无效对象 EVICTION/EVICTION_RETURN_TO_HEAD -> IDLE
startEvictionTest 无效对象 IDLE -> EVICTION

文档地址

Common-pool2 文档地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353