最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Apache組件分析對(duì)象池原理的實(shí)現(xiàn)案例分析

 更新時(shí)間:2022年04月06日 12:22:30   作者:知了一笑  
本文從對(duì)象池的一個(gè)簡(jiǎn)單案例切入,主要分析common-pool2組件關(guān)于:池、工廠、配置、對(duì)象管理幾個(gè)角色的源碼邏輯,并且參考其在Redis中的實(shí)踐,對(duì)Apache組件分析對(duì)象池原理相關(guān)知識(shí)感興趣的朋友一起看看吧

池塘里養(yǎng):Object;

一、設(shè)計(jì)與原理

1、基礎(chǔ)案例

首先看一個(gè)基于common-pool2對(duì)象池組件的應(yīng)用案例,主要有工廠類(lèi)、對(duì)象池、對(duì)象三個(gè)核心角色,以及池化對(duì)象的使用流程:

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ObjPool {
    public static void main(String[] args) throws Exception {
        // 聲明對(duì)象池
        DevObjPool devObjPool = new DevObjPool() ;
        // 池中借用對(duì)象
        DevObj devObj = devObjPool.borrowObject();
        System.out.println("Idle="+devObjPool.getNumIdle()+";Active="+devObjPool.getNumActive());
        // 使用對(duì)象
        devObj.devObjInfo();
        // 歸還給對(duì)象池
        devObjPool.returnObject(devObj);
        System.out.println("Idle="+devObjPool.getNumIdle()+";Active="+devObjPool.getNumActive());
        // 查看對(duì)象池
        System.out.println(devObjPool.listAllObjects());
    }
}
/**
 * 對(duì)象定義
 */
class DevObj {
    private static final Logger logger = LoggerFactory.getLogger(DevObj.class) ;
    public DevObj (){
        logger.info("build...dev...obj");
    }
    public void devObjInfo (){
        logger.info("dev...obj...info");
    }
}
/**
 * 對(duì)象工廠
 */
class DevObjFactory extends BasePooledObjectFactory<DevObj> {
    @Override
    public DevObj create() throws Exception {
        // 創(chuàng)建對(duì)象
        return new DevObj() ;
    }
    @Override
    public PooledObject<DevObj> wrap(DevObj devObj) {
        // 池化對(duì)象
        return new DefaultPooledObject<>(devObj);
    }
}
/**
 * 對(duì)象池
 */
class DevObjPool extends GenericObjectPool<DevObj> {
    public DevObjPool() {
        super(new DevObjFactory(), new GenericObjectPoolConfig<>());
    }
}

案例中對(duì)象是完全自定義的;對(duì)象工廠中則重寫(xiě)兩個(gè)核心方法:創(chuàng)建和包裝,以此創(chuàng)建池化對(duì)象;對(duì)象池的構(gòu)建依賴定義的對(duì)象工廠,配置采用組件提供的常規(guī)配置類(lèi);可以通過(guò)調(diào)整對(duì)象實(shí)例化的時(shí)間以及創(chuàng)建對(duì)象的個(gè)數(shù),初步理解對(duì)象池的原理。

2、接口設(shè)計(jì)

1.1 PooledObjectFactory 接口

  • 工廠類(lèi),負(fù)責(zé)對(duì)象實(shí)例化,創(chuàng)建、驗(yàn)證、銷(xiāo)毀、狀態(tài)管理等;
  • 案例中BasePooledObjectFactory類(lèi)則是該接口的基礎(chǔ)實(shí)現(xiàn);

1.2 ObjectPool 接口

  • 對(duì)象池,并且繼承Closeable接口,管理對(duì)象生命周期,以及活躍和空閑對(duì)象的數(shù)據(jù)信息獲?。?/li>
  • 案例中GenericObjectPool類(lèi)是對(duì)于該接口的實(shí)現(xiàn),并且是可配置化的方式;

1.3 PooledObject 接口

  • 池化對(duì)象,基于包裝類(lèi)被維護(hù)在對(duì)象池中,并且維護(hù)一些附加信息用來(lái)跟蹤,例如時(shí)間、狀態(tài);
  • 案例中采用DefaultPooledObject包裝類(lèi),實(shí)現(xiàn)該接口并且線程安全,注意工廠類(lèi)中的重寫(xiě);

3、運(yùn)行原理

通過(guò)對(duì)象池獲取對(duì)象,可能是通過(guò)工廠新創(chuàng)建的,也可能是空閑的對(duì)象;當(dāng)對(duì)象獲取成功且使用完成后,需要?dú)w還對(duì)象;在案例執(zhí)行過(guò)程中,不斷查詢對(duì)象池中空閑和活躍對(duì)象的數(shù)量,用來(lái)監(jiān)控池的變化。

二、構(gòu)造分析

1、對(duì)象池

public GenericObjectPool(final PooledObjectFactory<T> factory,final GenericObjectPoolConfig<T> config);

在完整的構(gòu)造方法中,涉及到三個(gè)核心對(duì)象:工廠對(duì)象、配置對(duì)象、雙端阻塞隊(duì)列;通過(guò)這幾個(gè)對(duì)象創(chuàng)建一個(gè)新的對(duì)象池;在config中提供了一些簡(jiǎn)單的默認(rèn)配置:例如maxTotal、maxIdle、minIdle等,也可以擴(kuò)展自定義配置;

2、雙端隊(duì)列

private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
public GenericObjectPool(final PooledObjectFactory<T> factory,final GenericObjectPoolConfig<T> config) {
    idleObjects = new LinkedBlockingDeque<>(config.getFairness());
}

LinkedBlockingDeque支持在隊(duì)列的首尾操作元素,例如添加和移除等;操作需要通過(guò)主鎖進(jìn)行加鎖,并且基于兩個(gè)狀態(tài)鎖進(jìn)行協(xié)作;

// 隊(duì)首節(jié)點(diǎn)
private transient LinkedBlockingDeque.Node<E> first;
// 隊(duì)尾節(jié)點(diǎn)
private transient LinkedBlockingDeque.Node<E> last;
// 主鎖
private final InterruptibleReentrantLock lock;
// 非空狀態(tài)鎖
private final Condition notEmpty;
// 未滿狀態(tài)鎖
private final Condition notFull;

關(guān)于鏈表和隊(duì)列的特點(diǎn),在之前的文章中有單獨(dú)分析過(guò),此處的源碼在JDK的容器中也很常見(jiàn),這里不在贅述,對(duì)象池的整個(gè)構(gòu)造有大致輪廓之后,下面再來(lái)細(xì)看對(duì)象的管理邏輯。

三、對(duì)象管理

1、添加對(duì)象

創(chuàng)建一個(gè)新對(duì)象并且放入池中,通常應(yīng)用在需要預(yù)加載的場(chǎng)景中;涉及到兩個(gè)核心操作:工廠創(chuàng)建對(duì)象,對(duì)象池化管理;

public void GenericObjectPool.addObject() throws Exception ;

2、借用對(duì)象

public T GenericObjectPool.borrowObject(final long borrowMaxWaitMillis) throws Exception ;

首先從隊(duì)列中獲取對(duì)象;如果沒(méi)有獲取到,調(diào)用工廠創(chuàng)建方法,之后池化管理;對(duì)象獲取之后會(huì)改變狀態(tài)為ALLOCATED使用中;最后經(jīng)過(guò)工廠的確認(rèn),完成對(duì)象獲取動(dòng)作;

3、歸還對(duì)象

public void GenericObjectPool.returnObject(final T obj) ;

歸還對(duì)象的時(shí)候,首先轉(zhuǎn)換為池化對(duì)象和標(biāo)記RETURNING狀態(tài);經(jīng)過(guò)多次校驗(yàn)判斷,如果失敗則銷(xiāo)毀該對(duì)象,并重新維護(hù)對(duì)象池中可用的空閑對(duì)象;最終對(duì)象被標(biāo)記為空閑狀態(tài),如果不超出最大空閑數(shù),則對(duì)象被放到隊(duì)列的某一端;

4、對(duì)象狀態(tài)

關(guān)于池化對(duì)象的狀態(tài)在PooledObjectState類(lèi)中有枚舉和描述,在圖中只是對(duì)部分幾個(gè)狀態(tài)流轉(zhuǎn)做示意,更多細(xì)節(jié)可以參考狀態(tài)類(lèi);

可以參考在上述案例中使用到的DefaultPooledObject默認(rèn)池化對(duì)象類(lèi)中相關(guān)方法,結(jié)合狀態(tài)枚舉,可以理解不同狀態(tài)之間的校驗(yàn)和轉(zhuǎn)換。

四、Redis應(yīng)用

Lettuce作為Redis高級(jí)的客戶端組件,通信層使用Netty組件,并且是線程安全,支持同步和異步模式,支持集群和哨兵模式;作為當(dāng)下項(xiàng)目中常用的配置,其底層對(duì)象池基于common-pool2組件。

1、配置管理

基于如下配置即表示采用Lettuce組件,其中涉及到池的幾個(gè)參數(shù)配置:最小空閑、最大活躍、最大空閑;這里可以對(duì)比GenericObjectPoolConfig中的配置:

spring:
  redis:
    host: ${REDIS_HOST:127.0.0.1}
    lettuce:
      pool:
        min-idle: 10
        max-active: 100
        max-idle: 100

2、源碼分析

圍繞對(duì)象池的特點(diǎn),自然去追尋源碼中關(guān)于:配置、工廠、對(duì)象幾個(gè)核心的角色類(lèi);從上述配置參數(shù)切入,可以很容易發(fā)現(xiàn)如下幾個(gè)類(lèi):

2.1 配置轉(zhuǎn)換

// 連接配置
class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
    private static class PoolBuilderFactory {
        // 構(gòu)建對(duì)象池配置
        private GenericObjectPoolConfig<?> getPoolConfig(RedisProperties.Pool properties) {
            GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
            config.setMaxTotal(properties.getMaxActive());
            config.setMaxIdle(properties.getMaxIdle());
            config.setMinIdle(properties.getMinIdle());
            return config;
        }
    }
}

這里將配置文件中Redis的相關(guān)參數(shù),構(gòu)建到GenericObjectPoolConfig類(lèi)中,即配置加載過(guò)程;

2.2 對(duì)象池構(gòu)造

class LettucePoolingConnectionProvider implements LettuceConnectionProvider {
    // 對(duì)象池核心角色
    private final GenericObjectPoolConfig poolConfig;
    private final BoundedPoolConfig asyncPoolConfig;
    private final Map<Class<?>, GenericObjectPool> pools = new ConcurrentHashMap(32);
    LettucePoolingConnectionProvider(LettuceConnectionProvider provider, LettucePoolingClientConfiguration config) {
        this.poolConfig = clientConfiguration.getPoolConfig();
        this.asyncPoolConfig = CommonsPool2ConfigConverter.bounded(this.config);
    }
}

在構(gòu)造方法中獲取對(duì)象池的配置信息,這里并沒(méi)有直接實(shí)例化池對(duì)象,而是采用ConcurrentHashMap容器來(lái)動(dòng)態(tài)維護(hù);

2.3 對(duì)象管理

class LettucePoolingConnectionProvider implements LettuceConnectionProvider {
    // 獲取Redis連接
    public <T extends StatefulConnection<?, ?>> T getConnection(Class<T> connectionType) {
        GenericObjectPool pool = (GenericObjectPool)this.pools.computeIfAbsent();
        StatefulConnection<?, ?> connection = (StatefulConnection)pool.borrowObject();
    }
    // 釋放Redis連接
    public void release(StatefulConnection<?, ?> connection) {
        GenericObjectPool<StatefulConnection<?, ?>> pool = (GenericObjectPool)this.poolRef.remove(connection);
    }
}

在獲取池對(duì)象時(shí),如果不存在則根據(jù)相關(guān)配置創(chuàng)建池對(duì)象,并維護(hù)到Map容器中,然后從池中借用Redis連接對(duì)象;釋放對(duì)象時(shí)首先判斷對(duì)象所屬的池,將對(duì)象歸還到相應(yīng)的池中。

最后總結(jié),本文從對(duì)象池的一個(gè)簡(jiǎn)單案例切入,主要分析common-pool2組件關(guān)于:池、工廠、配置、對(duì)象管理幾個(gè)角色的源碼邏輯,并且參考其在Redis中的實(shí)踐,只是冰山一角,像這種通用型并且應(yīng)用范圍廣的組件,很值得時(shí)常去讀一讀源碼,真的令人驚嘆其鬼斧天工的設(shè)計(jì)。

五、參考源碼

應(yīng)用倉(cāng)庫(kù):
https://gitee.com/cicadasmile/butte-flyer-parent

組件封裝:
https://gitee.com/cicadasmile/butte-frame-parent

到此這篇關(guān)于基于Apache組件分析對(duì)象池原理的文章就介紹到這了,更多相關(guān)Apache組件分析對(duì)象池原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java字符串比較獲取字符串出現(xiàn)次數(shù)的示例

    java字符串比較獲取字符串出現(xiàn)次數(shù)的示例

    java獲取一個(gè)字符串在整個(gè)字符串出現(xiàn)的次數(shù),下面寫(xiě)出我的思路和二個(gè)實(shí)現(xiàn)方法,大家參考使用吧
    2014-01-01
  • Win10?IDEA如何連接虛擬機(jī)中的Hadoop(HDFS)

    Win10?IDEA如何連接虛擬機(jī)中的Hadoop(HDFS)

    在虛擬機(jī)上配置Hadoop并修改core-site.xml文件,設(shè)置IP為局域網(wǎng)地址,IDEA中創(chuàng)建Maven項(xiàng)目,添加依賴,并檢查Hadoop重啟和端口轉(zhuǎn)發(fā),提供test.bat文件,通過(guò)修改IP簡(jiǎn)化使用過(guò)程
    2024-11-11
  • Maven 命令行打包 和 pom.xml的常用配置詳解

    Maven 命令行打包 和 pom.xml的常用配置詳解

    這篇文章主要介紹了Maven 命令行打包 和 pom.xml的常用配置詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • MyBatis insert語(yǔ)句返回主鍵和selectKey標(biāo)簽方式

    MyBatis insert語(yǔ)句返回主鍵和selectKey標(biāo)簽方式

    這篇文章主要介紹了MyBatis insert語(yǔ)句返回主鍵和selectKey標(biāo)簽方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • SpringBoot2使用JTA組件實(shí)現(xiàn)基于JdbcTemplate多數(shù)據(jù)源事務(wù)管理(親測(cè)好用)

    SpringBoot2使用JTA組件實(shí)現(xiàn)基于JdbcTemplate多數(shù)據(jù)源事務(wù)管理(親測(cè)好用)

    這篇文章主要介紹了SpringBoot2使用JTA組件實(shí)現(xiàn)基于JdbcTemplate多數(shù)據(jù)源事務(wù)管理(親測(cè)好用),在Spring?Boot?2.x中,整合了這兩個(gè)JTA的實(shí)現(xiàn)分別是Atomikos和Bitronix,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Java AOP知識(shí)詳細(xì)介紹

    Java AOP知識(shí)詳細(xì)介紹

    這篇文章主要介紹了Java AOP知識(shí)詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • JAVA中Integer值的范圍實(shí)例代碼

    JAVA中Integer值的范圍實(shí)例代碼

    這篇文章主要介紹了JAVA中Integer值的范圍實(shí)例代碼,需要的朋友可以參考下
    2017-09-09
  • 詳解Java 序列化與反序列化(Serialization)

    詳解Java 序列化與反序列化(Serialization)

    這篇文章主要介紹了Java 序列化與反序列化(Serialization),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí) 吧
    2019-03-03
  • SpringCloud之注冊(cè)中心之Nacos負(fù)載均衡詳解

    SpringCloud之注冊(cè)中心之Nacos負(fù)載均衡詳解

    Nacos提供多種負(fù)載均衡策略,包括權(quán)重、同機(jī)房、同地域、同環(huán)境等,服務(wù)下線和權(quán)重配置可以通過(guò)Nacos管理界面進(jìn)行,同時(shí),Nacos使用Raft算法選舉Leader節(jié)點(diǎn),若IP地址改變可能會(huì)影響Leader選舉,配置同集群優(yōu)先訪問(wèn)可以提高訪問(wèn)速度,通過(guò)配置集群名稱和負(fù)載均衡策略
    2025-03-03
  • 淺談一下Java中的幾種JVM級(jí)別的鎖

    淺談一下Java中的幾種JVM級(jí)別的鎖

    這篇文章主要介紹了淺談一下Java中的幾種JVM級(jí)別的鎖,當(dāng)存在安全漏洞時(shí),也必須有相應(yīng)的防護(hù)措施。順應(yīng)這種趨勢(shì),虛擬"鎖"被發(fā)明出來(lái),以解決線程的安全問(wèn)題。在這篇文章中,我們將研究多年來(lái)出現(xiàn)的?Java?中幾種典型的?JVM?級(jí)鎖,需要的朋友可以參考下
    2023-08-08

最新評(píng)論

涟水县| 大冶市| 富锦市| 广汉市| 陆良县| 灵宝市| 梅州市| 紫云| 金川县| 阿尔山市| 新和县| 灵石县| 丁青县| 乡宁县| 郧西县| 建德市| 朝阳区| 肇源县| 凌源市| 南宁市| 香河县| 金堂县| 灯塔市| 洪湖市| 皋兰县| 湖口县| 静安区| 福贡县| 历史| 平凉市| 鹤庆县| 栖霞市| 阳朔县| 彝良县| 潜江市| 遵化市| 廉江市| 西乡县| 东山县| 泰兴市| 大足县|