Jedis线程池的实现原理(二)


Jedis线程池的代码编写,也是基于池化技术的基础上的,只不过这里的对象池化中的对象,变成了线程罢了。

preparePool()池子准备

public void preparePool() throws Exception {
	//如果最小空闲数设置为大于等于1的话
	if (this.getMinIdle() >= 1) {
		//那么就需要保证最小空闲对象数
    	this.ensureMinIdle();
    }
}

转到ensureMinIdle()方法

void ensureMinIdle() throws Exception {
	//这里面是一个方法重载,输入参数为:要求的最小空闲数,always=true
	this.ensureIdle(this.getMinIdle(), true);
}

转到this.ensureIdle(this.getMinIdle(), true)方法

private void ensureIdle(int idleCount, boolean always) throws Exception {		
		//映入眼帘的是一个相当长的判断
		//只有满足下述的判断,才会进行后续操作,否则无动作
		//idleCount为我们传入的参数this.getMinIdle(),即我们设置的最小空闲数,要满足大于等于1的要求,算是一个重复判断,前面我们已经判断过一次了
		//并且!this.isClosed(),线程池不为关闭的状态
		//always我们已经传入为true了
        if (idleCount >= 1 && !this.isClosed() && 
        (always || this.idleObjects.hasTakeWaiters())) {
        	//当idleObjects里的对象数量小于最小空闲要求的时候,进行处理
        	//我们知道idleObjects是一个阻塞双向队列,里面有个全局锁
        	//该队列里面存放的是空闲对象
            while(this.idleObjects.size() < idleCount) {
            	//将要去创造出一个空闲对象,可能不会成功,因为超出设定的总数也是有可能的
                PooledObject<T> p = this.create();
                if (p == null) {
                    break;
                }
				//判断是否是后进先出
                if (this.getLifo()) {
                	//是的话,则将对象加到队首
                    this.idleObjects.addFirst(p);
                } else {
                	//否则,则将对象加到队尾
                    this.idleObjects.addLast(p);
                }
            }

            if (this.isClosed()) {
            	//如果这个时候检测到关闭
            	//则进行清空操作
            	//这样看来,这个this.isClosed()也是有一定的滞后性的
                this.clear();
            }

        }
    }

看了这几处代码,我们可以很清晰的觉察出preparePool()是什么情况,逻辑是这样的:先去判断设置的MinIdle数,就是池子里最小要保持的空闲对象数量,如果池子没满,并且空闲数量不足,那么就会去创建对象。

create()创造对象

private PooledObject<T> create() throws Exception {
		//localMaxTotal如果个人自定义没有设置的话,是-1
        int localMaxTotal = this.getMaxTotal();
        //意思就是说,如果没有对localMaxTotal进行设置,那么就不设置池子的上限,上限默认为Integer.MAX_VALUE
        if (localMaxTotal < 0) {
            localMaxTotal = 2147483647;
        }

        Boolean create = null;

        while(create == null) {
        	//synchronized是对makeObjectCountLock对象上锁啊
        	//初始化的时候makeObjectCountLock=new Object,只是为了对象头里的锁,该对象无意义
            synchronized(this.makeObjectCountLock) {
            	//createCount是一个原子long型数,先新增一个
                long newCreateCount = this.createCount.incrementAndGet();
                //如果这个新增后的数,超过了设定的池子的最大容量
                if (newCreateCount > (long)localMaxTotal) {
                	//改回去,不新增了
                    this.createCount.decrementAndGet();
                    //瞅瞅makeObjectCount那边还有没有剩余的容量
                    if (this.makeObjectCount == 0L) {
                    	//makeObjectCount为0,那就铁定生成不了新的对象了,早点散了吧,create设置为false
                        create = Boolean.FALSE;
                    } else {
                    	//等呗,等待makeObjectCountLock释放锁,再来一遍这个while循环
                        this.makeObjectCountLock.wait();
                    }
                } else {
                	//makeObjectCount增加1,这个意思就是在造途中的对象数量啊
                    ++this.makeObjectCount;
                    //可以建造新对象
                    create = Boolean.TRUE;
                }
            }
        }

        if (!create) {
        	//false,就是不能造新对象
            return null;
        } else {
        	//可以造新对象
            boolean var16 = false;

            PooledObject p;
            try {
                var16 = true;
                //传入的工厂类制造新对象
                p = this.factory.makeObject();
                var16 = false;
            } catch (Exception var19) {
                this.createCount.decrementAndGet();
                throw var19;
            } finally {
                if (var16) {
                	//var16==true只有可能是工厂类制造对象的时候报错了
                    synchronized(this.makeObjectCountLock) {
                    	//所以将makeObjectCount-1
                        --this.makeObjectCount;
                        //通知所有等待的线程
                        this.makeObjectCountLock.notifyAll();
                    }
                }
            }
			//制造对象完毕,那么在途制造数也是要减1的
            synchronized(this.makeObjectCountLock) {
                --this.makeObjectCount;
                //通知所有的对象
                this.makeObjectCountLock.notifyAll();
            }
			
            AbandonedConfig ac = this.abandonedConfig;
            //判断AbandonedConfig里的logAbandoned属性
            if (ac != null && ac.getLogAbandoned()) {
                p.setLogAbandoned(true);
            }
			//已经被创造的对象数量+1
            this.createdCount.incrementAndGet();
            //对象Map名册里加入这个新创造的对象
            this.allObjects.put(new IdentityWrapper(p.getObject()), p);
            //返回对象
            return p;
        }
    }

addObject()添加对象到队列

public void addObject() throws Exception {
		//确认对象池没有关闭,如果关闭了的话,就会抛出异常来
        this.assertOpen();
        //需要判断构造对象的工厂类是否不为空
        if (this.factory == null) {
        	//构造对象的工厂类为空,则抛出异常
            throw new IllegalStateException("Cannot add objects without a factory.");
        } else {
        	//构造新对象,create我们已经解析过了,如果不满足构造条件,也会抛出异常来
            PooledObject<T> p = this.create();
            //插入空闲对象队列
            this.addIdleObject(p);
        }
    }

看下具体是怎么插入的,除了判断是否后进先出之外,还调用了passivateObject方法,看了一下,这个是需要实现对象继承编写的方法,返回void,如果判断不通过,直接抛出异常。

private void addIdleObject(PooledObject<T> p) throws Exception {
        if (p != null) {
            this.factory.passivateObject(p);
            if (this.getLifo()) {
                this.idleObjects.addFirst(p);
            } else {
                this.idleObjects.addLast(p);
            }
        }
    }

borrowObject()借一个对象?对象还能借的?借了是不是要还回去?

public T borrowObject() throws Exception {
		//调用了一个重载方法,传入参数为最大等待时长
        return this.borrowObject(this.getMaxWaitMillis());
    }

我们逐行来分析borrowObject方法

public T borrowObject(long borrowMaxWaitMillis) throws Exception {
		//确认线程池现在是开启状态
        this.assertOpen();
        AbandonedConfig ac = this.abandonedConfig;
        //是否移除销毁很久不被使用的对象,这串代码就是做这个判断,并且执行移除、销毁的操作
        if (ac != null && ac.getRemoveAbandonedOnBorrow() && this.getNumIdle() < 2 && this.getNumActive() > this.getMaxTotal() - 3) {
            this.removeAbandoned(ac);
        }

        PooledObject<T> p = null;
        //资源耗尽是否阻塞
        boolean blockWhenExhausted = this.getBlockWhenExhausted();
        //当前时间
        long waitTime = System.currentTimeMillis();
		//自循环,需要里面的跳出来,才能解除循环
        while(true) {
            boolean create;
            do {
                do {
                    do {
                    	//如果对象已经得到那么就返回对象,顺便更新下对象借用情况
                        if (p != null) {
                            this.updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
                            return p.getObject();
                        }

                        create = false;
                        //从空闲对象队列里取出队首的对象
                        p = (PooledObject)this.idleObjects.pollFirst();
                        if (p == null) {
                        	//如果空闲队列为空,则创造一个
                            p = this.create();
                            if (p != null) {
                            	//创造成功,说明这个对象是新增的
                                create = true;
                            }
                        }
						//当资源枯竭的时候,则阻塞
                        if (blockWhenExhausted) {
                            if (p == null) {
                            	//这个默认是-1啊,借用对象最大等待时间
                                if (borrowMaxWaitMillis < 0L) {
                                	//不等了,直接拿
                                    p = (PooledObject)this.idleObjects.takeFirst();
                                } else {
                                    p = (PooledObject)this.idleObjects.pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS);
                                }
                            }

                            if (p == null) {
                            	//如果还是没有得到对象,那么就报错:获取空闲对象超时
                                throw new NoSuchElementException("Timeout waiting for idle object");
                            }
                        } else if (p == null) {
                            throw new NoSuchElementException("Pool exhausted");
                        }
						//我们总结一下,如何拿到PooledObject,首先去idleList拿,如果拿不到,则新建,如果新建不成,那就抛异常
						//拿到了之后,我们还需要判断PooledObject的状态,这里将是一个很重要的判断点,我们待会说
                        if (!p.allocate()) {
                            p = null;
                        }
                    } while(p == null);

                    try {
                    	//活化该对象
                        this.factory.activateObject(p);
                    } catch (Exception var13) {
                        try {
                        	//活化失败,则销毁该对象
                            this.destroy(p);
                        } catch (Exception var12) {
                        }

                        p = null;
                        if (create) {
                        	//如果这个对象是新建出来的,则抛出无法活化该对象的异常
                            NoSuchElementException nsee = new NoSuchElementException("Unable to activate object");
                            nsee.initCause(var13);
                            throw nsee;
                        }
                    }
                } while(p == null);
            } while(!this.getTestOnBorrow() && (!create || !this.getTestOnCreate()));
			
			//认证设为false
            boolean validate = false;
            //认证异常,初始化为空
            Throwable validationThrowable = null;

            try {
            	//验证对象的可用性,比如jedis是调用JRedis对象的ping()方法
                validate = this.factory.validateObject(p);
            } catch (Throwable var15) {
                PoolUtils.checkRethrow(var15);
                validationThrowable = var15;
            }

            if (!validate) {
            	//如果验证不通过
                try {
                	//销毁该对象
                    this.destroy(p);
					//在借用对象的过程中因为验证不通过而毁掉的对象数量+1
           			this.destroyedByBorrowValidationCount.incrementAndGet();
                } catch (Exception var14) {
                }

                p = null;
                if (create) {
                	//其实是新建成功一个对象了的,但是最后因为没有验证通过,所以这个对象新建失败
                    NoSuchElementException nsee = new NoSuchElementException("Unable to validate object");
                    nsee.initCause(validationThrowable);
                    throw nsee;
                }
            }
        }
    }

我们理一下逻辑,借用object,也是先问空闲队列借,借不到了才去创建,而且需要判断创建是否阻塞,以及传递阻塞最长时间,后面还需要用工厂里的验证方法验证该对象。

不过需要注意的是,其中的一个判断,p.allocate()判断该对象是否已经allocate

public synchronized boolean allocate() {
		//只有该池化对象的状态为IDLE的前提下,才会返回true
        if (this.state == PooledObjectState.IDLE) {
        	//将该对象的状态改为allocated,被放置
            this.state = PooledObjectState.ALLOCATED;
            //修改该对象上一次借用时间
            this.lastBorrowTime = System.currentTimeMillis();
            //修改该对象上一次使用时间,看起来,对象被借用了,默认对象被使用了
            this.lastUseTime = this.lastBorrowTime;
            //被借用的对象计数+1
            ++this.borrowedCount;
            if (this.logAbandoned) {
            	//如果设置日志抛出的话,调用快照
                this.borrowedBy.fillInStackTrace();
            }

            return true;
        } else if (this.state == PooledObjectState.EVICTION) {
        	//如果该对象是在EVICTION(被淘汰)状态的时候,则将状态改为EVICTION_RETURN_TO_HEAD(被淘汰的重新回来到队列头部?)
            this.state = PooledObjectState.EVICTION_RETURN_TO_HEAD;
            return false;
        } else {
            return false;
        }
    }

returnObject()有借得有还,我们看下返回代码

public void returnObject(T obj) {
		//查询一下,这个对象是否在全部对象Map表里
        PooledObject<T> p = (PooledObject)this.allObjects.get(new IdentityWrapper(obj));
        if (p == null) {
        	//如果不在,那么报错,归还的对象本身不在这个对象池里,那就无法归还该对
            if (!this.isAbandonedConfig()) {
                throw new IllegalStateException("Returned object not currently part of this pool");
            }
        } else {
            synchronized(p) {
            	//对该对象进行上锁,拿到锁了之后,查询状态
                PooledObjectState state = p.getState();
                //如果对象不是已放置(allocated)状态的话,那就返回不了对象池
                if (state != PooledObjectState.ALLOCATED) {
                    throw new IllegalStateException("Object has already been returned to this pool or is invalid");
                }
                //将对象状态改为RETURNING
                p.markReturning();
            }
			//对象激活时间
            long activeTime = p.getActiveTimeMillis();
           	//判断对象回归对象池是否也要进行测试,以及测试结果
            if (this.getTestOnReturn() && !this.factory.validateObject(p)) {
            	//测试结果失败,销毁对象
                try {
                    this.destroy(p);
                } catch (Exception var10) {
                    this.swallowException(var10);
                }
				//因为返回的对象失败了,所以尝试新造一个对象补给对象池
                try {
                    this.ensureIdle(1, false);
                } catch (Exception var9) {
                    this.swallowException(var9);
                }
				//返回对象计数+1
                this.updateStatsReturn(activeTime);
            } else {
                try {
                	//活化对象
                    this.factory.passivateObject(p);
                } catch (Exception var12) {
                	//如果活化失败,那么吞掉这个异常,重新创建一个对象出来补上
                    this.swallowException(var12);

                    try {
                        this.destroy(p);
                    } catch (Exception var8) {
                        this.swallowException(var8);
                    }

                    try {
                        this.ensureIdle(1, false);
                    } catch (Exception var7) {
                        this.swallowException(var7);
                    }

                    this.updateStatsReturn(activeTime);
                    return;
                }
				//将locate状态、returing状态的对象改为idle状态的对象
                if (!p.deallocate()) {
                	//失败,抛出异常,要么这个对象已经回归对象池了,要么该对象失效了
                    throw new IllegalStateException("Object has already been returned to this pool or is invalid");
                } else {
                	//获取最大空闲数
                    int maxIdleSave = this.getMaxIdle();
                    if (this.isClosed() || maxIdleSave > -1 && maxIdleSave <= this.idleObjects.size()) {
                    //如果对象池已经关闭,最大空闲数大于-1,并且小于等于目前空闲队列的对象数
                        try {
                        //则销毁对象
                            this.destroy(p);
                        } catch (Exception var11) {
                            this.swallowException(var11);
                        }
                    } else {
                    	//否则将对象返回空闲队列,根据是否Lifo
                        if (this.getLifo()) {
                            this.idleObjects.addFirst(p);
                        } else {
                            this.idleObjects.addLast(p);
                        }
						
                        if (this.isClosed()) {
                            this.clear();
                        }
                    }

                    this.updateStatsReturn(activeTime);
                }
            }
        }
    }

获取当前活跃对象数量

public int getNumActive() {
		//总的对象数量-空闲队列数量
        return this.allObjects.size() - this.idleObjects.size();
    }

use(T pooledObject)使用对象

public void use(T pooledObject) {
        AbandonedConfig ac = this.abandonedConfig;
        if (ac != null && ac.getUseUsageTracking()) {
            PooledObject<T> wrapper = (PooledObject)this.allObjects.get(new IdentityWrapper(pooledObject));
            //调用对象的use方法。。。
            wrapper.use();
        }

    }

close()关闭对象池

public void close() {
        if (!this.isClosed()) {
            synchronized(this.closeLock) {
                if (!this.isClosed()) {
                	//这里会开启evict
                    this.startEvictor(-1L);
                    this.closed = true;
                    this.clear();
                    this.jmxUnregister();
                    this.idleObjects.interuptTakeWaiters();
                }
            }
        }
    }

evict()驱逐?逐出?这么暴力的么,我们看看咋回事

在这里插入图片描述
参考
原来是叫淘汰机制啊,eviction policy原来是这么回事。

public void evict() throws Exception {
		//老规矩,先看看线程池有没有开放,没有开放直接抛异常
        this.assertOpen();
        if (this.idleObjects.size() > 0) {
        	//如果空闲队列有空闲对象
            PooledObject<T> underTest = null;
            //淘汰机制
            EvictionPolicy<T> evictionPolicy = this.getEvictionPolicy();
            //evictionLock对象锁,就跟那个makeCountLock差不多类型的,就是new 一个object
            synchronized(this.evictionLock) {
            	//构造淘汰机制config
                EvictionConfig evictionConfig = new EvictionConfig(this.getMinEvictableIdleTimeMillis(), this.getSoftMinEvictableIdleTimeMillis(), this.getMinIdle());
                //默认是false
                boolean testWhileIdle = this.getTestWhileIdle();
                int i = 0;
                //int numTestsPerEvictionRun = this.getNumTestsPerEvictionRun();默认值为3
                //return numTestsPerEvictionRun >= 0 ? Math.min(numTestsPerEvictionRun, this.idleObjects.size()) : (int)Math.ceil((double)this.idleObjects.size() / Math.abs((double)numTestsPerEvictionRun));
                //如果numTestsPerEvictionRun>=0,那么就取空闲队列的数量与这个设定值的最小值,如果小于0,则取空闲队列数量/numTestsPerEvictionRun,向上取整
                int m = this.getNumTests();
				//开启一个死循环
                while(true) {
                	//当所有对象全都被destry后,才会跳出该循环
                    if (i >= m) {
                        break;
                    }
					
                    if (this.evictionIterator == null || !this.evictionIterator.hasNext()) {
                        this.evictionIterator = new EvictionIterator(this, this.idleObjects);
                    }

                    if (!this.evictionIterator.hasNext()) {
                        return;
                    }

                    label81: {
                        try {
                            underTest = this.evictionIterator.next();
                        } catch (NoSuchElementException var15) {
                            --i;
                            this.evictionIterator = null;
                            break label81;
                        }
						//如果该对象的状态为PooledObjectState.IDLE,则将状态改为EVICTION并返回true,如果不是的话,则返回false
                        if (!underTest.startEvictionTest()) {
                            --i;
                        } else {
                            boolean evict;
                            try {
                            	//判断最小空闲数是否小于空闲队列对象数,并且,该对象的空闲时间是否超过设定的空闲软抛弃时间,或者空闲时间是否超过空闲抛弃时间
                                evict = evictionPolicy.evict(evictionConfig, underTest, this.idleObjects.size());
                            } catch (Throwable var14) {
                                PoolUtils.checkRethrow(var14);
                                this.swallowException(new Exception(var14));
                                evict = false;
                            }

                            if (evict) {
                            	//通过判断,则摧毁该对象
                                this.destroy(underTest);
                                //经过淘汰策略毁灭对象的计数+1
                                this.destroyedByEvictorCount.incrementAndGet();
                            } else {
                                if (testWhileIdle) {
                                    boolean active = false;

                                    try {
                                        //活化该对象
                                        this.factory.activateObject(underTest);
                                        active = true;
                                    } catch (Exception var13) {
                                        this.destroy(underTest);
                                        //活化失败可以直接将之除名
                                        //经过淘汰策略毁灭对象的计数+1
                                        this.destroyedByEvictorCount.incrementAndGet();
                                    }

                                    if (active) {
                                        if (!this.factory.validateObject(underTest)) {
                                            this.destroy(underTest);
                                            this.destroyedByEvictorCount.incrementAndGet();
                                        } else {
                                            try {
                                                this.factory.passivateObject(underTest);
                                            } catch (Exception var12) {
                                                this.destroy(underTest);
                                                this.destroyedByEvictorCount.incrementAndGet();
                                            }
                                        }
                                    }
                                }

                                if (!underTest.endEvictionTest(this.idleObjects)) {
                                }
                            }
                        }
                    }

                    ++i;
                }
            }
        }
		//移除抛出的配置
        AbandonedConfig ac = this.abandonedConfig;
        if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
            this.removeAbandoned(ac);
        }

    }

envict方法,就是要把所有的对象都淘汰掉。目标,对全部对象调用destroy方法

总结

至此我们将Pool池化技术里的准备池子,创造对象,新增对象,借用对象,返还对象,使用对象,清空对象,淘汰毁灭对象,关闭池子,这几个动作都解析了一遍。

其实挺简单的,就是维护一个阻塞双端队列,用来存放空闲对象,以及维护一个concurrentMap,用来存放池子里的所有对象。

以及池子里对象的状态的各种变化。

public enum PooledObjectState {
	//空闲状态
    IDLE,
    //被使用的状态
    ALLOCATED,
    //被淘汰的状态
    EVICTION,
    //被标记淘汰但是又把它搞回来了
    EVICTION_RETURN_TO_HEAD,
    //认证状态
    VALIDATION,
    //被使用前的认证状态
    VALIDATION_PREALLOCATED,
    //认证完返回空闲队列前的状态
    VALIDATION_RETURN_TO_HEAD,
    //该对象失效
    INVALID,
    //被遗弃
    ABANDONED,
    //返回池子的过程中
    RETURNING;

    private PooledObjectState() {
    }
}

下一章我们将简单聊一聊,Jedis对池化技术的使用,具体是怎么变成线程池的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rgbhi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值