apache common pool2簡介

一、摘要

apache common pool2 作為對象池模式的一種實(shí)現(xiàn),通過重用來分?jǐn)倧?fù)雜對象的創(chuàng)建代價(jià)。被廣泛應(yīng)用在各種數(shù)據(jù)庫連接池,線程池以及請求分發(fā)池中;其實(shí)現(xiàn)提供了一些參數(shù)來控制對象池的行為,了解這些參數(shù)對學(xué)習(xí)其他“池”技術(shù)很有必要。

二、對象池

對象池模式解決的問題

管理那些代表的現(xiàn)實(shí)資源或者通過重用來分?jǐn)偘嘿F初始化代價(jià)的對象。

對象的創(chuàng)建和銷毀在一定程度上會消耗系統(tǒng)的資源,雖然jvm的性能在近幾年已經(jīng)得到了很大的提高,對于多數(shù)對象來說,沒有必要利用對象池技術(shù)來進(jìn)行對象的創(chuàng)建和管理。但是對于有些對象來說,其創(chuàng)建的代價(jià)還是比較昂貴的,比如線程、tcp連接、數(shù)據(jù)庫連接等對象,因此對象池技術(shù)還是有其存在的意義。

對象池模式:

對象池模式管理一個(gè)可代替對象的集合。組件從池中借出對象,用它來完成一些任務(wù)并當(dāng)任務(wù)完成時(shí)歸還該對象。被歸還的對象接著滿足請求,不管是同一個(gè)組件還是其他組件的請求。

對象池模式

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn); 復(fù)用池中對象,沒有分配內(nèi)存和創(chuàng)建堆中對象的開銷, 沒有釋放內(nèi)存和銷毀堆中對象的開銷, 進(jìn)而減少垃圾收集器的負(fù)擔(dān), 避免內(nèi)存抖動;不必重復(fù)初始化對象狀態(tài)。
  • 缺點(diǎn):
    1. 并發(fā)環(huán)境下,對象池操作的同步成為一大開銷;
    2. 很難正確設(shè)置對象池大小,太小不起作用,太大浪費(fèi)資源。

三、 common pool2 核心

Apache Common-pool2包提供了一個(gè)通用的對象池技術(shù)的實(shí)現(xiàn)。可以很方便的基于它來實(shí)現(xiàn)自己的對象池,比如DBCP和Jedis他們的內(nèi)部對象池的實(shí)現(xiàn)就是依賴于Common-pool2。

Common-pool2由三大模塊組成:ObjectPoolPooledObjectPooledObjectFactory

它們的關(guān)系如下:

  • ObjectPool:提供所有對象的存取管理。
  • PooledObject:池化的對象,是對真正對象的一個(gè)包裝,加上了對象的一些其他信息,包括對象的狀態(tài)(已用、空閑),對象的創(chuàng)建時(shí)間等。其實(shí)現(xiàn)要求是線程安全的。
  • PooledObjectFactory:工廠類,負(fù)責(zé)池化對象的創(chuàng)建,對象的初始化,對象狀態(tài)的銷毀和對象狀態(tài)的驗(yàn)證。其實(shí)現(xiàn)要求是線程安全的。

通常,ObjectPool會持有PooledObjectFactory,將具體的對象的創(chuàng)建、初始化、銷毀等任務(wù)委托給PooledObjectFactory處理,工廠操作的對象是PooledObject,即具體的Object的包裝類。因此,獲取對象依賴ObjectPool而不是PooledObjectFactory。

池化對象于真正對象的區(qū)別

ObjectPool提供出去的對象是真正對象,而不是池化對象;池化對象是對象池的概念,為管理真正對象的相關(guān)細(xì)節(jié)提供支持。
PooledObject的實(shí)現(xiàn)會組合真正的對象。
PooledObjectFactory工廠產(chǎn)生的也是池化對象,而不是真正對象。

自定義對象池

以上三個(gè)抽象組件定義了 apache common pool2的標(biāo)準(zhǔn),自定義對象池分別實(shí)現(xiàn)這三個(gè)抽象組件:

  • ObjectPool的實(shí)現(xiàn),主要提供borrow/return池化對象,調(diào)用者可直接使用,或者通過組合的方式使用對象池。
  • PooledObjectFactory的實(shí)現(xiàn),用以產(chǎn)生池化對象。
  • PooledObject的實(shí)現(xiàn),包裝真正對象。

apache common pool2也提供了自己的對象池實(shí)現(xiàn)來簡化開發(fā),自定義對象池完全可以依賴這個(gè)實(shí)現(xiàn)獲得強(qiáng)大的對象池功能。

四、common pool2 自帶實(shí)現(xiàn)

apache common pool2提供了一些實(shí)現(xiàn)。這里介紹一種被廣泛使用的實(shí)現(xiàn):

  • ObjectPool的實(shí)現(xiàn):GenericObjectPool,提供了一個(gè)功能強(qiáng)大的對象池。
  • PooledObject的實(shí)現(xiàn):DefaultPooledObject
  • PooledObjectFactory的實(shí)現(xiàn):不可能提供默認(rèn)實(shí)現(xiàn),因?yàn)樯婕暗骄唧w對象的創(chuàng)建,需要使用者本身去實(shí)現(xiàn)。但是為了簡化開發(fā),提供了一個(gè)抽象的BasePooledObjectFactory,使用者可以選擇實(shí)現(xiàn)這個(gè)抽象類,而不是PooledObjectFactory來提供自己的池化對象工廠。

主要是對象池GenericObjectPool的實(shí)現(xiàn),主要介紹其borrow和return池化對象的方法。

GenericObjectPool
    - Map<IdentityWrapper<T>, PooledObject<T>> allObjects
    - LinkedBlockingDeque<PooledObject<T>> idleObjects

主要使用以上兩個(gè)數(shù)據(jù)結(jié)構(gòu)保持池化對象。

borrow的流程

  1. 從idle隊(duì)列取出第一個(gè)池化對象
  2. 若池化對象為null,嘗試使用工廠創(chuàng)建一個(gè)池化對象
  3. 創(chuàng)建若createCount小于maxTotal,則使用工廠新建池化對象,否則返回null
  4. blockWhenExhausted只是idle為空時(shí)是否等待,maxWaitMillis只是等待多久
  5. 池化對象!=null;factory#activateObject
  6. testOnBorrow || (create && testOnCreate) factory#validateObject

return的流程

  1. 根據(jù)obj從allObjects取出polledObject p
  2. 判空;將p狀態(tài)置為RETURN
  3. 若getTestOnReturn參數(shù)為true,進(jìn)行factory#validateObject
  4. 對p進(jìn)行factory#passivateObject,與初始化相反
  5. 更新p狀態(tài)為IDLE
  6. 歸還Pool:Pool的idle實(shí)例達(dá)到上限或者Pool已經(jīng)關(guān)閉,銷毀之,否則將p加入到LinkedBlockingDeque中。

自定義對象池可以依賴GenericObjectPool以及DefaultPooledObject,只實(shí)現(xiàn)PooledObjectFactory即可。

對象池屬性

org.apache.commons.pool2.impl.GenericObjectPool對象池屬性,控制對象池產(chǎn)生對象的行為;

全部屬性由org.apache.commons.pool2.impl.BaseGenericObjectPool描述:

屬性 說明
borrow:
maxTotal long;默認(rèn)-1 idle隊(duì)列為空,idle.len < maxTotal可創(chuàng)建,-1時(shí)maxTotal為整數(shù)最大值
blockWhenExhausted true[默認(rèn)]/false idle空,maxTotal達(dá)到,是否等待隊(duì)列
maxWaitMillis long;默認(rèn)-1 idle空,maxTotal達(dá)到blockWhenExhausted=true,等待隊(duì)列時(shí)長;-1一直等
testOnBorrow true/false[默認(rèn)] borrow時(shí),控制objFactory#validateObject
testOnCreate true/false[默認(rèn)] borrow時(shí),通過create獲得,控制objFactory#validateObject
return:
testOnReturn true/false[默認(rèn)] objPool#returnObj,控制 objFactory#validateObject
lifo true[默認(rèn)]/false true-LIFO idle隊(duì)列后進(jìn)先出; false-FIFO idle隊(duì)列先進(jìn)先出

五、自定義對象池

使用默認(rèn)對象池GenericObjectPool,只需定義池化對象工廠即可。

官方提供了demo 官方demo

以下為簡化,更容易看清本質(zhì):

池化對象工廠:產(chǎn)生StringBuffer對象

public class StringBufferFactory extends BasePooledObjectFactory<StringBuffer> {
    @Override
    public StringBuffer create() throws Exception {
        return new StringBuffer();
    }
    // 直接使用DefaultPooledObject包裝真正對象StringBuffer,提供池化對象
    @Override
    public PooledObject<StringBuffer> wrap(StringBuffer obj) {
        return new DefaultPooledObject<>(obj);
    }
    @Override
    public void passivateObject(PooledObject<StringBuffer> p) throws Exception {
        p.getObject().setLength(0);
    }
}

使用

public static void main(String[] args) throws Exception {
// 直接使用 apache common pool2提供的對象池,將創(chuàng)建池化對象細(xì)節(jié)委托給自定義的工廠即可。
GenericObjectPool<StringBuffer> pool = new GenericObjectPool<>(new StringBufferFactory());
// 從對象池借真正對象
StringBuffer stringBuffer = pool.borrowObject();
// do something with string buffer.
// 歸還
pool.returnObject(stringBuffer);
}

refer to

創(chuàng)建者模式-對象池模式(The Object Pool Pattern)

池化 - Apache Commons Pool

Apache Common Pool2 對象池應(yīng)用淺析

Apache Common-pool2對象池分析和應(yīng)用

apache-commons-pool-1.5.4 源碼解析

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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