欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

jedis的borrow行為方法源碼解讀

 更新時間:2023年09月22日 10:33:41   作者:codecraft  
這篇文章主要為大家介紹了jedis的borrow行為方法源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

本文主要研究一下jedis的borrow行為

borrowObject

org/apache/commons/pool2/impl/GenericObjectPool.java

public T borrowObject(final Duration borrowMaxWaitDuration) throws Exception {
        assertOpen();
        final AbandonedConfig ac = this.abandonedConfig;
        if (ac != null && ac.getRemoveAbandonedOnBorrow() && (getNumIdle() < 2) &&
                (getNumActive() > getMaxTotal() - 3)) {
            removeAbandoned(ac);
        }
        PooledObject<T> p = null;
        // Get local copy of current config so it is consistent for entire
        // method execution
        final boolean blockWhenExhausted = getBlockWhenExhausted();
        boolean create;
        final long waitTimeMillis = System.currentTimeMillis();
        while (p == null) {
            create = false;
            p = idleObjects.pollFirst();
            if (p == null) {
                p = create();
                if (p != null) {
                    create = true;
                }
            }
            if (blockWhenExhausted) {
                if (p == null) {
                    if (borrowMaxWaitDuration.isNegative()) {
                        p = idleObjects.takeFirst();
                    } else {
                        p = idleObjects.pollFirst(borrowMaxWaitDuration);
                    }
                }
                if (p == null) {
                    throw new NoSuchElementException(appendStats(
                            "Timeout waiting for idle object, borrowMaxWaitDuration=" + borrowMaxWaitDuration));
                }
            } else if (p == null) {
                throw new NoSuchElementException(appendStats("Pool exhausted"));
            }
            if (!p.allocate()) {
                p = null;
            }
            if (p != null) {
                try {
                    factory.activateObject(p);
                } catch (final Exception e) {
                    try {
                        destroy(p, DestroyMode.NORMAL);
                    } catch (final Exception e1) {
                        // Ignore - activation failure is more important
                    }
                    p = null;
                    if (create) {
                        final NoSuchElementException nsee = new NoSuchElementException(
                                appendStats("Unable to activate object"));
                        nsee.initCause(e);
                        throw nsee;
                    }
                }
                if (p != null && getTestOnBorrow()) {
                    boolean validate = false;
                    Throwable validationThrowable = null;
                    try {
                        validate = factory.validateObject(p);
                    } catch (final Throwable t) {
                        PoolUtils.checkRethrow(t);
                        validationThrowable = t;
                    }
                    if (!validate) {
                        try {
                            destroy(p, DestroyMode.NORMAL);
                            destroyedByBorrowValidationCount.incrementAndGet();
                        } catch (final Exception e) {
                            // Ignore - validation failure is more important
                        }
                        p = null;
                        if (create) {
                            final NoSuchElementException nsee = new NoSuchElementException(
                                    appendStats("Unable to validate object"));
                            nsee.initCause(validationThrowable);
                            throw nsee;
                        }
                    }
                }
            }
        }
        updateStatsBorrow(p, Duration.ofMillis(System.currentTimeMillis() - waitTimeMillis));
        return p.getObject();
    }
  • borrowObject方法會開啟一個while循環(huán),條件是p為null,也就是要獲取到p或者是內(nèi)部自己跳出循環(huán);idleObjects.pollFirst()從連接池獲取,如果為null則執(zhí)行create,之后是blockWhenExhausted的判斷邏輯,如果create出來的為null,則阻塞等待takeFirst或者pollFirst(borrowMaxWaitDuration),如果還是null則拋出NoSuchElementException;如果blockWhenExhausted為false但是create為null則拋出Pool exhausted
  • 如果不是null,則再次確認下object的狀態(tài),如果變更狀態(tài)(PooledObjectState.IDLE-->PooledObjectState.ALLOCATED)不成功則返回null;接著執(zhí)行factory.activateObject(p)方法,如果出現(xiàn)異常則destory掉(jedis這里只是在db不一樣的時候會重新select,默認可以理解為空操作),緊接著是testOnBorrow的邏輯
  • 這里就是如果idleObjects.pollFirst()為null會觸發(fā)create,如果還是null則直接拋出NoSuchElementException異常,跳出循環(huán);只有在不為null且allocate失敗的時候會重置為null繼續(xù)循環(huán);另外如果是create出來的但是activate不成功也會拋出NoSuchElementException異常,跳出循環(huán)

create

/**
     * Attempts to create a new wrapped pooled object.
     * <p>
     * If there are {@link #getMaxTotal()} objects already in circulation
     * or in process of being created, this method returns null.
     * </p>
     *
     * @return The new wrapped pooled object
     *
     * @throws Exception if the object factory's {@code makeObject} fails
     */
    private PooledObject<T> create() throws Exception {
        int localMaxTotal = getMaxTotal();
        // This simplifies the code later in this method
        if (localMaxTotal < 0) {
            localMaxTotal = Integer.MAX_VALUE;
        }
        final long localStartTimeMillis = System.currentTimeMillis();
        final long localMaxWaitTimeMillis = Math.max(getMaxWaitDuration().toMillis(), 0);
        // Flag that indicates if create should:
        // - TRUE:  call the factory to create an object
        // - FALSE: return null
        // - null:  loop and re-test the condition that determines whether to
        //          call the factory
        Boolean create = null;
        while (create == null) {
            synchronized (makeObjectCountLock) {
                final long newCreateCount = createCount.incrementAndGet();
                if (newCreateCount > localMaxTotal) {
                    // The pool is currently at capacity or in the process of
                    // making enough new objects to take it to capacity.
                    createCount.decrementAndGet();
                    if (makeObjectCount == 0) {
                        // There are no makeObject() calls in progress so the
                        // pool is at capacity. Do not attempt to create a new
                        // object. Return and wait for an object to be returned
                        create = Boolean.FALSE;
                    } else {
                        // There are makeObject() calls in progress that might
                        // bring the pool to capacity. Those calls might also
                        // fail so wait until they complete and then re-test if
                        // the pool is at capacity or not.
                        makeObjectCountLock.wait(localMaxWaitTimeMillis);
                    }
                } else {
                    // The pool is not at capacity. Create a new object.
                    makeObjectCount++;
                    create = Boolean.TRUE;
                }
            }
            // Do not block more if maxWaitTimeMillis is set.
            if (create == null &&
                (localMaxWaitTimeMillis > 0 &&
                 System.currentTimeMillis() - localStartTimeMillis >= localMaxWaitTimeMillis)) {
                create = Boolean.FALSE;
            }
        }
        if (!create.booleanValue()) {
            return null;
        }
        final PooledObject<T> p;
        try {
            p = factory.makeObject();
            if (getTestOnCreate() && !factory.validateObject(p)) {
                createCount.decrementAndGet();
                return null;
            }
        } catch (final Throwable e) {
            createCount.decrementAndGet();
            throw e;
        } finally {
            synchronized (makeObjectCountLock) {
                makeObjectCount--;
                makeObjectCountLock.notifyAll();
            }
        }
        final AbandonedConfig ac = this.abandonedConfig;
        if (ac != null && ac.getLogAbandoned()) {
            p.setLogAbandoned(true);
            p.setRequireFullStackTrace(ac.getRequireFullStackTrace());
        }
        createdCount.incrementAndGet();
        allObjects.put(new IdentityWrapper<>(p.getObject()), p);
        return p;
    }
create方法不會判斷createCount,如果超出則返回null,如果等待超出maxWait也會返回null;如果判斷要創(chuàng)建則通過factory.makeObject(),另外針對testOnCreate且validateObject不通過的也返回null,如果是有異常則直接拋出

makeObject

redis/clients/jedis/JedisFactory.java

@Override
  public PooledObject<Jedis> makeObject() throws Exception {
    Jedis jedis = null;
    try {
      jedis = new Jedis(jedisSocketFactory, clientConfig);
      jedis.connect();
      return new DefaultPooledObject<>(jedis);
    } catch (JedisException je) {
      if (jedis != null) {
        try {
          jedis.quit();
        } catch (RuntimeException e) {
          logger.warn("Error while QUIT", e);
        }
        try {
          jedis.close();
        } catch (RuntimeException e) {
          logger.warn("Error while close", e);
        }
      }
      throw je;
    }
  }
JedisFactory的makeObject會創(chuàng)建Jedis然后執(zhí)行connect,如果有JedisException則拋出,這個也會直接跳出borrowObject的循環(huán),直接給到調(diào)用方

activateObject

redis/clients/jedis/JedisFactory.java

public void activateObject(PooledObject<Jedis> pooledJedis) throws Exception {
    final BinaryJedis jedis = pooledJedis.getObject();
    if (jedis.getDB() != clientConfig.getDatabase()) {
      jedis.select(clientConfig.getDatabase());
    }
  }
JedisFactory的activateObject就是判斷db跟配置的是不是一樣,不一樣則重新select

testOnBorrow

if (p != null && getTestOnBorrow()) {
                    boolean validate = false;
                    Throwable validationThrowable = null;
                    try {
                        validate = factory.validateObject(p);
                    } catch (final Throwable t) {
                        PoolUtils.checkRethrow(t);
                        validationThrowable = t;
                    }
                    if (!validate) {
                        try {
                            destroy(p, DestroyMode.NORMAL);
                            destroyedByBorrowValidationCount.incrementAndGet();
                        } catch (final Exception e) {
                            // Ignore - validation failure is more important
                        }
                        p = null;
                        if (create) {
                            final NoSuchElementException nsee = new NoSuchElementException(
                                    appendStats("Unable to validate object"));
                            nsee.initCause(validationThrowable);
                            throw nsee;
                        }
                    }
                }
    public static void checkRethrow(final Throwable t) {
        if (t instanceof ThreadDeath) {
            throw (ThreadDeath) t;
        }
        if (t instanceof VirtualMachineError) {
            throw (VirtualMachineError) t;
        }
        // All other instances of Throwable will be silently swallowed
    }
testOnBorrow的邏輯就是執(zhí)行validateObject方法,如果是ThreadDeath或者VirtualMachineError才會重新拋出,否則吞掉,之后判斷validate結果,如果不成功則執(zhí)行destory方法,重新設置為null,但是如果這個是create出來的則拋出NoSuchElementException

小結

jedis的borrow行為是在while循環(huán)里頭去獲取的,一般是在allocate變更狀態(tài)不成功(PooledObjectState.IDLE-->PooledObjectState.ALLOCATED)的時候會重新設置null,繼續(xù)循環(huán)

  • idleObjects.pollFirst()為null會觸發(fā)create,如果還是null則拋出NoSuchElementException(Pool exhausted)跳出循環(huán);如果blockWhenExhausted為true,block之后獲取到的還是null,也會拋出NoSuchElementException(Timeout waiting for idle object)跳出循環(huán);如果觸發(fā)create操作,且create拋出JedisException,這個也會直接跳出borrowObject的循環(huán),直接給到調(diào)用方
  • borrow出來不會null的執(zhí)行activateObject,jedis這里只是在db不一樣的時候會重新select,默認可以理解為空操作

最后是testOnBorrow的邏輯,如果有異常,則針對create出來的則拋出NoSuchElementException跳出循環(huán),否則重置為null繼續(xù)循環(huán)

總結

一下就是如果是create有異常(JedisException)則直接拋出,如果borrow不到(即使經(jīng)過create)也會拋出NoSuchElementException(具體可能是Pool exhausted或者Timeout waiting for idle object),如果有testOnBorrow不通過且是create出來的,也會拋出NoSuchElementException(Unable to validate object)

以上就是jedis的borrow行為方法源碼解讀的詳細內(nèi)容,更多關于jedis borrow方法的資料請關注腳本之家其它相關文章!

相關文章

  • java線程池ExecutorService超時處理小結

    java線程池ExecutorService超時處理小結

    使用ExecutorService時,設置子線程執(zhí)行超時是一個常見需求,本文就來詳細的介紹一下ExecutorService超時的三種方法,感興趣的可以了解一下
    2024-09-09
  • java web實現(xiàn)自動登錄

    java web實現(xiàn)自動登錄

    這篇文章主要為大家詳細介紹了java web實現(xiàn)自動登錄,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 老生常談Java中List與ArrayList的區(qū)別

    老生常談Java中List與ArrayList的區(qū)別

    大家都知道List是接口,ArrayList是List接口的一個實現(xiàn)類,接下來通過本文給大家介紹Java中List與ArrayList的區(qū)別,需要的朋友可以參考下
    2022-08-08
  • java?SpringBoot?分布式事務的解決方案(JTA+Atomic+多數(shù)據(jù)源)

    java?SpringBoot?分布式事務的解決方案(JTA+Atomic+多數(shù)據(jù)源)

    這篇文章主要介紹了java?SpringBoot?分布式事務的解決方案(JTA+Atomic+多數(shù)據(jù)源),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    2022-08-08
  • HashMap實現(xiàn)保存兩個key相同的數(shù)據(jù)

    HashMap實現(xiàn)保存兩個key相同的數(shù)據(jù)

    這篇文章主要介紹了HashMap實現(xiàn)保存兩個key相同的數(shù)據(jù)操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 基于ElasticSearch Analyzer的使用規(guī)則詳解

    基于ElasticSearch Analyzer的使用規(guī)則詳解

    這篇文章主要介紹了基于ElasticSearch Analyzer的使用規(guī)則,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java中EnumMap代替序數(shù)索引代碼詳解

    Java中EnumMap代替序數(shù)索引代碼詳解

    這篇文章主要介紹了Java中EnumMap代替序數(shù)索引代碼詳解,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • Java8 新特性Lambda表達式實例詳解

    Java8 新特性Lambda表達式實例詳解

    這篇文章主要介紹了Java8 新特性Lambda表達式實例詳解的相關資料,需要的朋友可以參考下
    2017-03-03
  • java中Integer包裝類裝箱的一個細節(jié)詳解

    java中Integer包裝類裝箱的一個細節(jié)詳解

    Java中的Integer是int的包裝類型,下面這篇文章主要給大家介紹了關于java中Integer包裝類裝箱的一個細節(jié)的相關資料,文中介紹的這個細節(jié)挺重要的,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起看看吧
    2018-07-07
  • Java Springboot之Spring家族的技術體系

    Java Springboot之Spring家族的技術體系

    今天帶大家來學習Spring家族的技術體系,文中有非常詳細的圖文介紹及代碼示例,對正在學習java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05

最新評論