对象池解析

对象池解析对象池解析JedisPool中创建连接池中使用newnewGenericObjectPool(巴拉巴拉);例如:newGenericObjectPool<Jedis>(newJedisFactory(uri,Protocol.*DEFAULT_TIMEOUT*,Pro

大家好,欢迎来到IT知识分享网。

对象池解析

JedisPool 中创建连接池中使用 new new GenericObjectPool

(巴拉巴拉);

例如: new GenericObjectPool<Jedis>(new JedisFactory(uri,Protocol.*DEFAULT_TIMEOUT*, Protocol.*DEFAULT_TIMEOUT*, null), new GenericObjectPoolConfig());

image

GenericObjectPool:

borrowObject() : 从对象池中获取一个对象
步骤:

  1. 验证连接池是否关闭
  2. 判断是否移除异常对象
  3. 获取对象
  4. 获取对象失败如果有阻塞等待标识———继续获取
  5. 对象的激活和校验
public T borrowObject(final long borrowMaxWaitMillis) throws Exception {
        //第一步: 检查一下对象池的状态是否关闭, 如果关闭了会抛出异常IllegalStateException
        assertOpen();
        //第二步: 判断是否需要移除那些长时间运行未被回收的对象
        final AbandonedConfig ac = this.abandonedConfig;
        if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
                (getNumIdle() < 2) &&
                (getNumActive() > getMaxTotal() - 3) ) {
            removeAbandoned(ac);
        }
        // 定义一个具体的实例包装对象, T为要返回的实例
        PooledObject<T> p = null;

       // 为避免执行过程中blockWhenExhausted被其他线程更改, 所以存储在此局部变量中
        final boolean blockWhenExhausted = getBlockWhenExhausted();
        // 为标识是否为新创建的对象
        boolean create;
        // 定义开始时间, 后续用来校验borrowMaxWaitMillis是否超时
        final long waitTime = System.currentTimeMillis();
        // 第三步: 获取实例
        while (p == null) {
            create = false;
            /*
                从空闲对象中弹出第一个元素(后进先出), 没有则null,
                为null创建一个新对象, 并将create设为true
            */
            p = idleObjects.pollFirst(); 
            if (p == null) {
                p = create();
                if (p != null) {
                    create = true;
                }
            }
            // 如果设置了对象耗尽阻塞等待标识
            if (blockWhenExhausted) {
                if (p == null) { //说明创建失败
                    // 如果设置了一个无效等待时间, 就一直从空闲队列中获取直到获取到
                    // 如果设置了有效的等待时间, 也会从空闲队列中获取对象, 但是有时间限制
                    if (borrowMaxWaitMillis < 0) {
                        p = idleObjects.takeFirst();
                    } else {
                        p = idleObjects.pollFirst(borrowMaxWaitMillis,
                                TimeUnit.MILLISECONDS);
                    }
                }
                //如果此时还为null, 说明从空闲队列没有获得对象, 抛出等待空闲对象超时的异常
                if (p == null) {
                    throw new NoSuchElementException(
                            "Timeout waiting for idle object");
                }
            } else {
                // 如果没有设置对象阻塞等待标识, 还没创建新对象成功, 说明连接池耗尽, 抛出异常
                if (p == null) {
                    throw new NoSuchElementException("Pool exhausted");
                }
            }
            // 如果分配失败(可能是被其他线程抢走了), 则设置为null,重新循环获得
            if (!p.allocate()) {
                p = null;
            }

            // 第四步: 获取对象的激活
            if (p != null) {
                try {
                    // 激活获得的对象
                    factory.activateObject(p);
                } catch (final Exception e) {
                    try {
                        // 激活对象失败, 对象进行销毁
                        destroy(p);
                    } catch (final Exception e1) {
                        // Ignore - activation failure is more important
                    }
                    p = null;
                    if (create) {
                        final NoSuchElementException nsee = new NoSuchElementException(
                                "Unable to activate object");
                        nsee.initCause(e);
                        throw nsee;
                    }
                }
                // 第五步: 对象校验
                // testOnBorrow属性为true 或者 新创建的对象、并且testOnCreate属性为true
                //   这个逻辑也就意味着在配置testOnBorrow和testOnCreate的关系是
                //   testOnBorrow如果设置为true,无论testOnCreate真假,无论是新创建对象还是空闲对象,则都会进行validate
                //   testOnBorrow如果设置为fasle,那么只有testOnCreate为真,且确实是新创建的对象才会validate
                if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
                    boolean validate = false; //标识是否校验通过
                    Throwable validationThrowable = null; // 保存检验时产生的异常
                    try {
                        // 校验
                        validate = factory.validateObject(p);
                    } catch (final Throwable t) {
                        // 检查异常是否要抛出, ThreadDeath和VirtualMachineError两种Error则抛出, 其他的存在validationThrowable
                        PoolUtils.checkRethrow(t);
                        validationThrowable = t;
                    }
                    // 校验失败, 销毁对象
                    if (!validate) {
                        try {
                            destroy(p);
                            destroyedByBorrowValidationCount.incrementAndGet();
                        } catch (final Exception e) {
                            // Ignore - validation failure is more important
                        }
                        p = null;
                        if (create) {
                            final NoSuchElementException nsee = new NoSuchElementException(
                                    "Unable to validate object");
                            nsee.initCause(validationThrowable);
                            throw nsee;
                        }
                    }
                }
            }
        }
       
        updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
        // 成功获得对象
        return p.getObject();
    }

returnObject() : 向对象池中归还一个对象

步骤 :

  1. 判断归还对象是否在对象池中, 不在返回, 在继续操作
  2. 归还对象, 修改对象状态
  3. 判断是否校验对象
  4. 重置对象属性
  5. 判断现在对象池对象数量是否大于对象池中对象的最大空闲数量, 是——销毁, 不是——归 还对象
public void returnObject(final T obj) {
        // allObjects 对象池, 查看当前对象是否还在对象池中
        final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));

        /**
           p为null, 说明对象需要归还的对象已经不在对象池中了, 其原因有可能是配置了abandonedConfig,
           没配置说明不是被强制回收的, 抛出异常---返回的对象不是此连接池的
        **/
        if (p == null) {
            if (!isAbandonedConfig()) {
                throw new IllegalStateException(
                        "Returned object not currently part of this pool");
            }
            return; // Object was abandoned and removed
        }
        // 加锁保证内部执行的原子性
        synchronized(p) {
            // 获得当前归还对象状态, 状态不是ALLOCATED说明对象已经归还过了或者对象无效因而抛出异常
            final PooledObjectState state = p.getState();
            if (state != PooledObjectState.ALLOCATED) {
                throw new IllegalStateException(
                        "Object has already been returned to this pool or is invalid");
            }
            // 更改对象状态
            p.markReturning();
        }
        // 获取对象的使用时间
        final long activeTime = p.getActiveTimeMillis();

        // 配置了testOnReturn=true, 需要校验一下对象
        if (getTestOnReturn()) {
            // 校验该对象(发送了一个ping命令), 校验失败则销毁该对象
            if (!factory.validateObject(p)) {
                try {
                    destroy(p);
                } catch (final Exception e) {
                    swallowException(e);
                }
                try {
                    // ensureIdle的第一个入参指定创建几个对象, 
                    // 第二个入参true是指直接创建, false是指有调用者等待时就创建
                    // 当有调用方在排队等待时, 创建一个对象加入
                    ensureIdle(1, false);
                } catch (final Exception e) {
                    swallowException(e);
                }
                updateStatsReturn(activeTime);
                return;
            }
        }

        // 重置对象属性 (passivateObject()方法里面什么都没写)
        try {
            factory.passivateObject(p);
        } catch (final Exception e1) {
            swallowException(e1);
            try {
                destroy(p);
            } catch (final Exception e) {
                swallowException(e);
            }
            try {
                ensureIdle(1, false);
            } catch (final Exception e) {
                swallowException(e);
            }
            updateStatsReturn(activeTime);
            return;
        }

        // 改状态为IDLE, 更改失败抛出异常
        if (!p.deallocate()) {
            throw new IllegalStateException(
                    "Object has already been returned to this pool or is invalid");
        }

        // 获得对象池的最大空闲数量
        final int maxIdleSave = getMaxIdle();
        // 如果对象池被关闭,或者对象池的空闲数量超出最大值则销毁对象, 否则将对象加入对象池
        if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
            try {
                destroy(p);
            } catch (final Exception e) {
                swallowException(e);
            }
        } else {
            if (getLifo()) {
                idleObjects.addFirst(p);
            } else {
                idleObjects.addLast(p);
            }
            if (isClosed()) {
                clear();
            }
        }
        updateStatsReturn(activeTime);
    }

startEvictor 启动一个回收器

GenericObjectPool 构造方法中都会调用startEvictor 启动一个回收器, 如果当前有回收器在运行则停掉老的, 根据入参给定的延时时间重新创建一个使用

/**
   evictor : 回收器对象
   evictionIterator : 回收迭代器
   注意: 开启回收器时delay若 < 0,不会创建新的回收器, 当前存在回收器会将回收器取消,
        不存在则什么都没做· 
**/
final void startEvictor(final long delay) {
        synchronized (evictionLock) {
            // 如果当前回收器不为null, 说明当前存在回收器, 则需要关闭老的回收器,
            // 并将回收器和回收迭代器置空便于垃圾回收
            if (null != evictor) {
                EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis,
                                     TimeUnit.MILLISECONDS);
                evictor = null;
                evictionIterator = null;
            }
            // 如果 delay 大于 0 , 创建一个新的回收器
            if (delay > 0) {
                evictor = new Evictor();
                EvictionTimer.schedule(evictor, delay, delay);
            }
        }
    }

evict() : 回收空闲对象

getNumTests() : 获得需要回收的空闲对象数量

步骤:

  1. 检测对象池状态
  2. 遍历回收对象的次数进行回收(获得空闲对象→判断是否可回收→不可回收判断是否存活和能使用)
  3. 处理遗弃的对象
public void evict() throws Exception {
        // 校验对象池状态, 是否被关闭
        assertOpen();
        // 如果对象池中的空闲对象 > 0
        if (idleObjects.size() > 0) {

            PooledObject<T> underTest = null;
            // 获得一个回收策略, 其中有默认的回收策略
            final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();

            synchronized (evictionLock) {
                // 创建回收配置对象
                final EvictionConfig evictionConfig = new EvictionConfig(
                        getMinEvictableIdleTimeMillis(), // 指定超过该时间被回收, 为-1不生效
                        getSoftMinEvictableIdleTimeMillis(), // 指对象池超过最小空闲数量, 并超过该时间, 回收
                        getMinIdle()); // 对象池的最小空闲对象数量
                // 为true, 检验对象的有效性
                final boolean testWhileIdle = getTestWhileIdle();

                // 遍历需要回收对象数量的次数
                for (int i = 0, m = getNumTests(); i < m; i++) {
                    // 迭代器为null, 重新创建一个
                    if (evictionIterator == null || !evictionIterator.hasNext()) {
                        evictionIterator = new EvictionIterator(idleObjects);
                    }
                    // 迭代器中没有空闲对象数量, 直接返回
                    if (!evictionIterator.hasNext()) {
                        // Pool exhausted, nothing to do here
                        return;
                    }
                    // 获得待处理的空闲对象, 获取失败进行下一次遍历
                    try {
                        underTest = evictionIterator.next();
                    } catch (final NoSuchElementException nsee) {
                        // Object was borrowed in another thread
                        // Don't count this as an eviction test so reduce i;
                        i--;
                        evictionIterator = null;
                        continue;
                    }
                    // 进行空闲对象检测,并更改状态, 检测失败有可能是因为空闲对象被其他调用者获得了
                    if (!underTest.startEvictionTest()) {
                        // Object was borrowed in another thread
                        // Don't count this as an eviction test so reduce i;
                        i--;
                        continue;
                    }
                    // evict 获得对象是否可回收
                    boolean evict;
                    try {
                        evict = evictionPolicy.evict(evictionConfig, underTest,
                                idleObjects.size());
                    } catch (final Throwable t) {
                        // Slightly convoluted as SwallowedExceptionListener
                        // uses Exception rather than Throwable
                        PoolUtils.checkRethrow(t);
                        swallowException(new Exception(t));
                        // Don't evict on error conditions
                        evict = false;
                    }
                    // evict = true对象可以被清理 销毁对象
                    if (evict) {
                        destroy(underTest);
                        destroyedByEvictorCount.incrementAndGet();
                    } else {
                        // 对象不能被清理, 检测对象是否可用
                        if (testWhileIdle) {
                            boolean active = false;
                            // 检测对象是否存活, 不存活销毁
                            try {
                                factory.activateObject(underTest);
                                active = true;
                            } catch (final Exception e) {
                                destroy(underTest);
                                destroyedByEvictorCount.incrementAndGet();
                            }
                            // 检测对象是否可用, 不可用销毁
                            if (active) {
                                if (!factory.validateObject(underTest)) {
                                    destroy(underTest);
                                    destroyedByEvictorCount.incrementAndGet();
                                } else {
                                    try {
                                        factory.passivateObject(underTest);
                                    } catch (final Exception e) {
                                        destroy(underTest);
                                        destroyedByEvictorCount.incrementAndGet();
                                    }
                                }
                            }
                        }
                        // 不可回收的空闲对象重置状态
                        if (!underTest.endEvictionTest(idleObjects)) {
                            // TODO - May need to add code here once additional
                            // states are used
                        }
                    }
                }
            }
        }
        // 将遗弃的对象进行处理
        final AbandonedConfig ac = this.abandonedConfig;
        if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
            removeAbandoned(ac);
        }
    }

ensureMinIdle() : 确保线程中有足够的对象

private void ensureIdle(final int idleCount, final boolean always) throws Exception {
        // 如果需要创建空闲的对象数量 < 1, 对象池关闭, alway为false并且无等待调用方, 则不会创建对象
        if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
            return;
        }
        
        // 空闲数量小于idleCount 创建对象
        while (idleObjects.size() < idleCount) {
            final PooledObject<T> p = create();
            if (p == null) {
                break;
            }
            // 确定从开头加还是结尾加
            if (getLifo()) {
                idleObjects.addFirst(p);
            } else {
                idleObjects.addLast(p);
            }
        }
        if (isClosed()) {
            clear();
        }
    }

Evictor 回收器对象

class Evictor extends TimerTask {
        // run方法, 主要是 回收需要回收的对象, 确保最小数量的空闲连接就可以
        @Override
        public void run() {
            // 获得当前线程的classLoader
            final ClassLoader savedClassLoader =
                    Thread.currentThread().getContextClassLoader();
            try {
                // 如果factoryClassLoader为空,说明对象池的类加载器是根加载器
                // 不为null, 说明对象池的加载器很可能是AppClassLoader或者某个框架自定义的加载器
                if (factoryClassLoader != null) {
                    final ClassLoader cl = factoryClassLoader.get();
                    if (cl == null) {
                        // 任务状态置为CANCELLED
                        cancel();
                        return;
                    }
                    Thread.currentThread().setContextClassLoader(cl);
                }

                try {
                    // 执行清除的操作
                    evict();
                } catch(final Exception e) {
                    swallowException(e);
                } catch(final OutOfMemoryError oome) {
                    oome.printStackTrace(System.err);
                }
                try {
                    // 确保线程池中有足够的对象
                    ensureMinIdle();
                } catch (final Exception e) {
                    swallowException(e);
                }
            } finally {
                Thread.currentThread().setContextClassLoader(savedClassLoader);
            }
        }
    }

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30620.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信