大家好,欢迎来到IT知识分享网。
对象池解析
JedisPool 中创建连接池中使用 new new GenericObjectPool
(巴拉巴拉);
例如: new GenericObjectPool<Jedis>(new JedisFactory(uri,Protocol.*DEFAULT_TIMEOUT*, Protocol.*DEFAULT_TIMEOUT*, null), new GenericObjectPoolConfig());
GenericObjectPool:
borrowObject() : 从对象池中获取一个对象
步骤:
- 验证连接池是否关闭
- 判断是否移除异常对象
- 获取对象
- 获取对象失败如果有阻塞等待标识———继续获取
- 对象的激活和校验
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() : 向对象池中归还一个对象
步骤 :
- 判断归还对象是否在对象池中, 不在返回, 在继续操作
- 归还对象, 修改对象状态
- 判断是否校验对象
- 重置对象属性
- 判断现在对象池对象数量是否大于对象池中对象的最大空闲数量, 是——销毁, 不是——归 还对象
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() : 获得需要回收的空闲对象数量
步骤:
- 检测对象池状态
- 遍历回收对象的次数进行回收(获得空闲对象→判断是否可回收→不可回收判断是否存活和能使用)
- 处理遗弃的对象
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