Apache Commons-pool2要點整理

為什么要用對象池

解決大對象的創(chuàng)建和銷毀時的資源消耗捌锭。所以,常見的對象池有數(shù)據(jù)庫連接池取视、線程池等

Apache Commons-pool2幾個重要對象

  • ObjectPool<T>
    實現(xiàn)對對象存取和狀態(tài)管理的池實現(xiàn)鬼雀;如:線程池顷窒、數(shù)據(jù)庫連接池
public interface ObjectPool<T> {
  //從池子中獲取一個對象
  T borrowObject() throws Exception, NoSuchElementException,
            IllegalStateException;
  //將對象用完后放回到對象池
  void returnObject(T obj) throws Exception;
  //廢棄對象
  void invalidateObject(T obj) throws Exception;
  //增加對象
  void addObject() throws Exception, IllegalStateException,
            UnsupportedOperationException;
  //獲取空閑對象個數(shù)
  int getNumIdle();
  //獲取活躍對象個數(shù)
  int getNumActive();
  //清除池,池可用
  void clear() throws Exception, UnsupportedOperationException;
  //關(guān)閉池源哩,池不可用
  void close();
}
  • PooledObject<T> extends Comparable<PooledObject<T>>
    被池化的對象的包裝類鞋吉,在原對象的基礎(chǔ)上添加了一些附加的信息,比如說狀態(tài)信息励烦,創(chuàng)建時間谓着,激活時間,關(guān)閉時間等
  • PooledObjectFactory<T>
    被池化對象的工廠類坛掠,用于創(chuàng)建對象赊锚、銷毀對象、校驗對象狀態(tài)等

一個示例屉栓,驗證對象的獲取和釋放

  1. 被池化的對象
/**
 *  被池化的對象舷蒲, 此對象將放入對象池中
 *
 */
public class BigObject {

    private String key;
    
    public BigObject(String key) {
        this.key = key;
    }
    
    public BigObject() {}
}
  1. 被池化對象的工廠
/**
 * 生產(chǎn)被池化對象的工廠
 * @author yaowan
 *
 */
public class BigObjectFactory extends BasePooledObjectFactory<BigObject> {

    @Override
    public BigObject create() throws Exception {
        return new BigObject("1");
    }

    @Override
    public PooledObject<BigObject> wrap(BigObject obj) {
        return new DefaultPooledObject<BigObject>(obj);
    }
    /**
     * testOnCreate,testOnBorrow之一設(shè)置為true時,
     * objectPool.borrowObject()被調(diào)用時友多,會調(diào)用此方法
     * 
     */
    @Override
    public boolean validateObject(PooledObject<BigObject> p) {
        //用一個隨機(jī)數(shù)據(jù)來模擬對象是否失效
        if (new Random().nextInt(10) < 6) {
            System.out.println(Thread.currentThread().getName()+" 對象失效牲平。。域滥。纵柿。。骗绕。藐窄。");
            return false;
        }
        System.out.println(Thread.currentThread().getName()+" 對象有效。酬土。荆忍。。。刹枉。叽唱。");
        return true;
    }
}
  1. 使用對象池中的對象
public class BigObjectProvider {
    private ObjectPool<BigObject> objectPool;
    public BigObjectProvider(ObjectPool<BigObject> objectPool) {
        this.objectPool = objectPool;
    }
    public void use() {
        System.out.println(Thread.currentThread().getName() + " 準(zhǔn)備取對象。微宝。棺亭。。蟋软。镶摘。");
        System.out.println(objectPool.getNumActive() + "," + objectPool.getNumIdle());
        // 獲得對應(yīng)key的對象
        BigObject connectionTest1 = null;
        try {
            connectionTest1 = objectPool.borrowObject();
            System.out.println(Thread.currentThread().getName() + " borrowObject = {" + connectionTest1 + "}");
            System.out.println(Thread.currentThread().getName() + " 已取得對象,正在使用中岳守。凄敢。。湿痢。涝缝。。譬重。");
            Thread.sleep(2000);

        } catch (NoSuchElementException e) {
            
            System.out.println(convert2String(org.apache.commons.lang3.exception.ExceptionUtils.getStackFrames(e)));
            //再次請求使用
            use();
        } catch (IllegalStateException e) {
            //對象放回對象池出錯拒逮,拋出來的異常
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connectionTest1 != null) {
                // 釋放對象
                try {
                    objectPool.returnObject(connectionTest1);
                    System.out.println(
                            Thread.currentThread().getName() + objectPool.getNumActive() + "," + objectPool.getNumIdle());
                    System.out.println(Thread.currentThread().getName() + " 歸還對象。臀规。滩援。。塔嬉。狠怨。。");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static String convert2String(String[] strings) {
        StringBuilder builder = new StringBuilder();
        for (String string : strings) {
            builder.append(string).append("\n");
        }
        return builder.toString();
    } 
}
/**
 * 模擬使用過程
 * 啟動兩個線程來競爭使用邑遏,通過打印的信息來熟知整個過程
 *
 */
public class UseCase {

    public static void main(String[] args) {
        
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        //當(dāng)“連接池”中active數(shù)量達(dá)到閥值時佣赖,即“鏈接”資源耗盡時,連接池需要采取的手段
        config.setBlockWhenExhausted(true);
        config.setMaxTotal(1);
        //設(shè)置為true時记盒,在GenericObjectPool<T>.borrowObject(long)方法調(diào)用獲取不到對象時憎蛤,會調(diào)用
        //PooledObjectFactory<T>.validateObject(PooledObject<T>)驗證是否要釋放對象
        //此時對象池中沒有對象時,會拋出NoSuchElementException異常
        config.setTestOnBorrow(true);
        config.setTestOnCreate(true);
        
        BigObjectFactory factory = new BigObjectFactory();
        
        final ObjectPool<BigObject> objectPool = new GenericObjectPool<>(PoolUtils.synchronizedPooledFactory(factory),config);
        
        final BigObjectProvider provider = new BigObjectProvider(objectPool);
        final int execNum = 3;
        new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i=0;i< execNum;i++) {
                    
                    System.out.println(Thread.currentThread().getName()+" 第"+i+"次使用前");
                    provider.use();
                    System.out.println(Thread.currentThread().getName()+" 第"+i+"次使用后");

                }
            }

        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i=0;i< execNum;i++) {
                    System.out.println(Thread.currentThread().getName()+" 第"+i+"次使用前");
                    provider.use();
                    System.out.println(Thread.currentThread().getName()+" 第"+i+"次使用后");
                }
            }
        }).start();
    }
}
  1. 運行結(jié)果
Thread-1 第0次使用前
Thread-1 準(zhǔn)備取對象纪吮。俩檬。。碾盟。棚辽。。
0,0
Thread-2 第0次使用前
Thread-2 準(zhǔn)備取對象冰肴。屈藐。榔组。。联逻。搓扯。
0,0
Thread-1 對象失效。包归。锨推。。公壤。换可。。
java.util.NoSuchElementException: Unable to validate object
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:506)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
    at org.poker.common.objectpool.BigObjectProvider.use(BigObjectProvider.java:23)
    at org.poker.common.objectpool.UseCase$1.run(UseCase.java:41)
    at java.lang.Thread.run(Thread.java:745)
Thread-1 準(zhǔn)備取對象厦幅。锦担。。慨削。。套媚。
0,0
Thread-1 對象有效缚态。。堤瘤。玫芦。。本辐。桥帆。
Thread-1 borrowObject = {org.poker.common.objectpool.BigObject@6f8225a}
Thread-1 已取得對象,正在使用中慎皱。老虫。。茫多。祈匙。。天揖。
Thread-10,1
Thread-1 歸還對象夺欲。。今膊。些阅。。斑唬。市埋。
Thread-1 第0次使用后
Thread-1 第1次使用前
Thread-1 準(zhǔn)備取對象黎泣。。腰素。聘裁。。弓千。
Thread-2 對象失效衡便。。洋访。镣陕。。姻政。呆抑。
1,0
Thread-2 對象有效。汁展。鹊碍。。食绿。侈咕。。
Thread-2 borrowObject = {org.poker.common.objectpool.BigObject@19ebee92}
Thread-2 已取得對象器紧,正在使用中耀销。。铲汪。熊尉。。掌腰。狰住。
Thread-20,1
Thread-2 歸還對象。齿梁。转晰。。士飒。查邢。。
Thread-2 第0次使用后
Thread-2 第1次使用前
Thread-2 準(zhǔn)備取對象酵幕。扰藕。。芳撒。邓深。未桥。
Thread-1 對象失效。芥备。冬耿。。萌壳。亦镶。。
1,0
Thread-1 對象有效袱瓮。缤骨。。尺借。绊起。。。
Thread-1 borrowObject = {org.poker.common.objectpool.BigObject@39c46fff}
Thread-1 已取得對象,正在使用中谴咸。。笋鄙。。谨读。。坛吁。
Thread-10,1
Thread-1 歸還對象劳殖。。拨脉。哆姻。。玫膀。矛缨。
Thread-1 第1次使用后
Thread-1 第2次使用前
Thread-1 準(zhǔn)備取對象。帖旨。箕昭。。解阅。落竹。
Thread-2 對象失效。货抄。朱转。藤为。。。。
1,0
Thread-2 對象有效。忌愚。硕糊。撬腾。。。碟刺。
Thread-2 borrowObject = {org.poker.common.objectpool.BigObject@1dd47977}
Thread-2 已取得對象者填,正在使用中蜜暑。铐姚。。肛捍。隐绵。。拙毫。
Thread-20,1
Thread-2 歸還對象依许。。缀蹄。峭跳。。缺前。蛀醉。
Thread-2 第1次使用后
Thread-2 第2次使用前
Thread-2 準(zhǔn)備取對象。诡延。滞欠。古胆。肆良。。
Thread-1 對象失效逸绎。惹恃。。棺牧。巫糙。。颊乘。
1,0
Thread-1 對象失效参淹。醉锄。。浙值。恳不。。开呐。
java.util.NoSuchElementException: Unable to validate object
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:506)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
    at org.poker.common.objectpool.BigObjectProvider.use(BigObjectProvider.java:23)
    at org.poker.common.objectpool.UseCase$1.run(UseCase.java:41)
    at java.lang.Thread.run(Thread.java:745)
Thread-1 準(zhǔn)備取對象烟勋。。筐付。卵惦。。瓦戚。
0,0
Thread-1 對象有效沮尿。。伤极。蛹找。。哨坪。庸疾。
Thread-1 borrowObject = {org.poker.common.objectpool.BigObject@507e8ea4}
Thread-1 已取得對象,正在使用中当编。届慈。。忿偷。金顿。。鲤桥。
Thread-10,1
Thread-2 對象有效揍拆。。茶凳。嫂拴。。贮喧。筒狠。
Thread-1 歸還對象。箱沦。辩恼。。。灶伊。疆前。
Thread-1 第2次使用后
Thread-2 borrowObject = {org.poker.common.objectpool.BigObject@507e8ea4}
Thread-2 已取得對象,正在使用中聘萨。峡继。。匈挖。碾牌。。儡循。
Thread-20,1
Thread-2 歸還對象舶吗。。择膝。誓琼。。肴捉。腹侣。
Thread-2 第2次使用后

通過在對象池中放入1個對象,來觀察對象的獲取和釋放過程齿穗,以及在并發(fā)環(huán)境下對象安全問題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末傲隶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子窃页,更是在濱河造成了極大的恐慌跺株,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脖卖,死亡現(xiàn)場離奇詭異乒省,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)畦木,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門袖扛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人十籍,你說我怎么就攤上這事蛆封。” “怎么了妓雾?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵娶吞,是天一觀的道長垒迂。 經(jīng)常有香客問我械姻,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任楷拳,我火速辦了婚禮绣夺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘欢揖。我一直安慰自己陶耍,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布她混。 她就那樣靜靜地躺著烈钞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坤按。 梳的紋絲不亂的頭發(fā)上毯欣,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機(jī)與錄音臭脓,去河邊找鬼酗钞。 笑死,一個胖子當(dāng)著我的面吹牛来累,可吹牛的內(nèi)容都是我干的砚作。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼嘹锁,長吁一口氣:“原來是場噩夢啊……” “哼葫录!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起领猾,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤压昼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后瘤运,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窍霞,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年拯坟,在試婚紗的時候發(fā)現(xiàn)自己被綠了但金。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡郁季,死狀恐怖冷溃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情梦裂,我是刑警寧澤似枕,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站年柠,受9級特大地震影響凿歼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一答憔、第九天 我趴在偏房一處隱蔽的房頂上張望味赃。 院中可真熱鬧,春花似錦虐拓、人聲如沸心俗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽城榛。三九已至,卻和暖如春态兴,著一層夾襖步出監(jiān)牢的瞬間吠谢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工诗茎, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留工坊,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓敢订,卻偏偏與公主長得像王污,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子楚午,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法昭齐,類相關(guān)的語法,內(nèi)部類的語法矾柜,繼承相關(guān)的語法阱驾,異常的語法,線程的語...
    子非魚_t_閱讀 31,664評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理怪蔑,服務(wù)發(fā)現(xiàn)里覆,斷路器,智...
    卡卡羅2017閱讀 134,711評論 18 139
  • 小編費力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡單原理和應(yīng)用缆瓣。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 4,596評論 1 114
  • 1喧枷,關(guān)于格局 如果說2016年是幾大巨頭劃分展館的牡丹斗艷,那2017家電展呈現(xiàn)的是一場百花起放弓坞。遙想去年的家電展...
    燕子回堂閱讀 281評論 0 0
  • 萬家燈火隧甚,飄雪 街燈下牽你的手 零下六度吻你的嘴 擁抱 我說,在一起吧 你說渡冻,好 冬戚扳,春、夏族吻、秋 今年的冬天還會下...
    冷笑話高手你翔哥閱讀 173評論 0 1