jinfeng_wang

          G-G-S,D-D-U!

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks
          https://my.oschina.net/xinxingegeya/blog/391560

          commons.pool2 對象池的使用

          <dependency>     <groupId>org.apache.commons</groupId>     <artifactId>commons-pool2</artifactId>     <version>2.3</version> </dependency>


          池對象工廠 PooledObjectFactory和池對象 DefaultPooledObject

          先了解個概念:

          池對象工廠(PooledObjectFactory接口):用來創建池對象, 將不用的池對象進行鈍化(passivateObject), 對要使用的池對象進行激活(activeObject), 對池對象進行驗證(validateObject), 對有問題的池對象進行銷毀(destroyObject)等工作

          PooledObjectFactory是一個池化對象工廠接口,定義了生成對象、激活對象、鈍化對象、銷毀對象的方法,如下

          public interface PooledObjectFactory<T{     PooledObject<T> makeObject() throws Exception;      void destroyObject(PooledObject<T> var1) throws Exception;      boolean validateObject(PooledObject<T> var1);      void activateObject(PooledObject<T> var1) throws Exception;      void passivateObject(PooledObject<T> var1) throws Exception; }

          如果需要使用Commons-Pool,那么你就需要提供一個PooledObjectFactory接口的具體實現。一個比較簡單的辦法就是,繼承BasePooledObjectFactory這個抽象類。而繼承這個抽象類,只需要實現兩個方法:create()和wrap(T obj)。

          實現create()方法很簡單,而實現wrap(T obj)也有捷徑,可以使用類DefaultPooledObject,代碼可以參考如下:

          import org.apache.commons.pool2.BasePooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject;  /**  * Created by liyanxin on 2015/3/25.  */ public class PooledStringBufferFactory extends BasePooledObjectFactory<StringBuffer{      @Override     public StringBuffer create() throws Exception {         return new StringBuffer(16);     }      @Override     public PooledObject<StringBuffer> wrap(StringBuffer stringBuffer) {         return new DefaultPooledObject<StringBuffer>(stringBuffer);     } }

          當然還有其他的池對象工廠,如KeyedPooledObjectFactory,和PooledObjectFactory接口類似,只是在相關的方法中多了Key參數,如下,

          public interface KeyedPooledObjectFactory<K,V{         PooledObject<V> makeObject(K key) throws Exception;        void destroyObject(K key, PooledObject<V> p) throws Exception;      boolean validateObject(K key, PooledObject<V> p);         void activateObject(K key, PooledObject<V> p) throws Exception;      void passivateObject(K key, PooledObject<V> p) throws Exception; }


          創建對象池 GenericObjectPool

          在org.apache.commons.pool2.impl中預設了三個可以直接使用的對象池:GenericObjectPool、GenericKeyedObjectPool和SoftReferenceObjectPool。

          通常使用GenericObjectPool來創建對象池,如果是對象池是Keyed的,那么可以使用GenericKeyedObjectPool來創建對象池。這兩個類都提供了豐富的配置選項。這兩個對象池的特點是可以設置對象池中的對象特征,包括LIFO(后進先出)方式、最大空閑數、最小空閑數、是否有效性檢查等等。兩者的區別如前面所述,后者支持Keyed。

          而SoftReferenceObjectPool對象池,它利用一個java.util.ArrayList對象來保存對象池里的對象。不過它并不在對象池里直接保存對象本身,而是保存它們的“軟引用”

          (Soft Reference)。這種對象池的特色是:可以保存任意多個對象,不會有容量已滿的情況發生;在對象池已空的時候,調用它的borrowObject方法,會自動返回新創建的實例;可以在初始化同時,在池內預先創建一定量的對象;當內存不足的時候,池中的對象可以被Java虛擬機回收。

          舉個例子:

          new GenericObjectPool<StringBuffer>(new PooledStringBufferFactory());

          我們也可以使用GenericObjectPoolConfig來對上面創建的對象池進行一些參數配置,創建的Config參數,可以使用setConfig方法傳給對象池,也可以在對象池的構造方法中作為參數傳入。

          舉個例子:

          GenericObjectPoolConfig conf = new GenericObjectPoolConfig(); conf.setMaxTotal(20); conf.setMaxIdle(10); ... GenericObjectPool<StringBuffer> pool = new GenericObjectPool<StringBuffer>(new PooledStringBufferFactory(), conf);


          使用對象池

          對象池使用起來很方便,簡單一點就是使用borrowObject和returnObject兩個方法,直接給參考代碼吧:

          borrowObject部分代碼,具體請看源碼:借出池對象,通過新建create()或從idleObjects雙端隊列中返回池對象。idleObjects是一個雙端隊列,保存返回對象池的對象,下次用的時候按照LIFO的原則(或其他原則)借出對象。

          public T borrowObject(long borrowMaxWaitMillis) throws Exception {     PooledObject<T> p = null;      while (p == null) {         create = false;         if (blockWhenExhausted) {             p = idleObjects.pollFirst();             if (p == null) {                 p = create();                 if (p != null) {                     create = true;                 }             }             if (p == null) {                 if (borrowMaxWaitMillis < 0) {                     p = idleObjects.takeFirst();                 } else {                     p = idleObjects.pollFirst(borrowMaxWaitMillis,                             TimeUnit.MILLISECONDS);                 }             }             if (p == null) {                 throw new NoSuchElementException(                         "Timeout waiting for idle object");             }             if (!p.allocate()) {                 p = null;             }         } else {             p = idleObjects.pollFirst();             if (p == null) {                 p = create();                 if (p != null) {                     create = true;                 }             }         }     }     return p.getObject(); }

          returnObject方法,部分代碼,具體請看源碼:返回池對象,放入idleObjects雙端隊列保存。

          關鍵代碼:

          public void returnObject(T obj{     PooledObject<T> p = allObjects.get(obj);      int maxIdleSave = getMaxIdle();     if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {         try {             destroy(p);         } catch (Exception e) {             swallowException(e);         }     } else {         if (getLifo()) {             idleObjects.addFirst(p);         } else {             idleObjects.addLast(p);         }     }     updateStatsReturn(activeTime); }

          這只是大體上的邏輯,還有更多的細節邏輯控制。比如什么時候銷毀,什么時候創建等等。

          posted on 2016-12-20 15:36 jinfeng_wang 閱讀(540) 評論(0)  編輯  收藏 所屬分類: 2016-thinking
          主站蜘蛛池模板: 栾川县| 收藏| 株洲县| 镇赉县| 靖西县| 麻城市| 包头市| 清镇市| 嘉义县| 怀远县| 思茅市| 米易县| 连平县| 綦江县| 南溪县| 井冈山市| 苍南县| 武强县| 通化市| 旺苍县| 浙江省| 赤城县| 玉门市| 田阳县| 北川| 县级市| 荣成市| 临洮县| 长汀县| 车致| 永嘉县| 西华县| 永宁县| 安徽省| 扶风县| 巴塘县| 永仁县| 丰顺县| 定南县| 北宁市| 九台市|