利用Apache commons pool2構建池應用

commons pool2與commons pool1還是有很大的差別的,本文主要記錄利用commons pool2構建自己的池應用。

1 依賴的引入

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.4.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

2 構建自己的池應用

ps:本文構建一個string池,從池獲取string對象
2.1 構建自己的PooledObjectFactory

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

public interface PooledObjectFactory<T> {
  /**
  * 生成對象
  */
  PooledObject<T> makeObject() throws Exception;

 /**
  * 銷燬對象
  */
  void destroyObject(PooledObject<T> p) throws Exception;

 /**
  * 驗證對象
  */
  boolean validateObject(PooledObject<T> p);

 /**
  * 激活對象
  */
  void activateObject(PooledObject<T> p) throws Exception;

 /**
  * 鈍化對象
  */
  void passivateObject(PooledObject<T> p) throws Exception;
}

如果需要使用Commons-Pool構建構建自己的池應用,那麼就需要提供一個PooledObjectFactory接口的具體實現。當然也可以繼承BasePooledObjectFactory這個抽象類。本文實現PooledObjectFactory接口,如下所示:

public class StringFactory implements PooledObjectFactory<String>{
    public StringFactory(){
        System.out.println("init string factory..");
    }
    public void activateObject(PooledObject<String> pool) throws Exception {
        // TODO Auto-generated method stub

    }

    public void destroyObject(PooledObject<String> pool) throws Exception {
        String str = pool.getObject();
        if(str!=null){
            str=null;
            System.out.println(str+" destroy...");
        }
    }

    public PooledObject<String> makeObject() throws Exception {
        String i = UUID.randomUUID().toString();
        System.out.println("make "+i+" success...");
        return new DefaultPooledObject<String>(i);
    }

    public void passivateObject(PooledObject<String> pool) throws Exception {
        // TODO Auto-generated method stub

    }

    public boolean validateObject(PooledObject<String> pool) {
        // TODO Auto-generated method stub
        return false;
    }

}

2.2 創建對象池

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

通常使用GenericObjectPool來創建對象池,如果是對象池是Keyed的,那麼可以使用GenericKeyedObjectPool來創建對象池。

而SoftReferenceObjectPool對象池,它利用一個java.util.ArrayList對象來保存對象池裏的對象。不過它並不在對象池裏直接保存對象本身,而是保存它們的“軟引用”。
(1)GenericObjectPool的使用
如下所示爲GenericObjectPool的使用:

        GenericObjectPoolConfig conf = new GenericObjectPoolConfig();
        conf.setMaxTotal(10);
        GenericObjectPool<String> pool = new GenericObjectPool<String>(new StringFactory(), conf);
        for(int i=0;i<15;i++){
            System.out.println(i+":");
            try {
                String str = pool.borrowObject();
                System.out.println(str);
            } catch (Exception e) {
                e.printStackTrace();
            }           
       }

上例中設置GenericObjectPool的maxTotal爲10,開啓一個循環(循環次數爲15),每次從池中拿一個對象,由於池的大小爲10,每次拿到對象之後沒有釋放,所以程序block在i=10處。
這裏寫圖片描述
下面的例子爲每次拿到對象之後,處理完再釋放:

GenericObjectPoolConfig conf = new GenericObjectPoolConfig();
        conf.setMaxTotal(10);
        GenericObjectPool<String> pool = new GenericObjectPool<String>(new StringFactory(), conf);
        for(int i=0;i<15;i++){
            System.out.println(i+":");
            try {
                String str = pool.borrowObject();
                System.out.println(str);
                pool.returnObject(str);
            } catch (Exception e) {
                e.printStackTrace();
            }           
       }

其運行結果如下:
這裏寫圖片描述

(2)自定義pool
如下所示爲自定義Pool實現了Closeable接口,定義自己的獲取資源與釋放資源的方法。

public class Pool implements Closeable{
  public GenericObjectPool<String> innerPool;

  public Pool() {

  }

  public Pool(final GenericObjectPoolConfig poolConfig,PooledObjectFactory<String> factory){
     initPool(poolConfig, factory); 
  }

  public void close() throws IOException {
    innerPool.close();
  }

  public void initPool(final GenericObjectPoolConfig poolConfig,PooledObjectFactory<String> factory){
     if(this.innerPool!=null){
         System.out.println("innerPool is not null,destroy it..");
         innerPool.close();
     } 
     this.innerPool = new GenericObjectPool<String>(factory,poolConfig);
  }

  public String getResource(){
    String str = "";
    try {
        str=this.innerPool.borrowObject();
        System.out.println("get resource success..:"+str);
    } catch (Exception e) { 
        e.printStackTrace();
        System.out.println("get resource error...");
    }finally{
        return str;
    }   
  }

  public void returnResourceObject(final String resource){
      if(resource==null){
          return;
      }
      innerPool.returnObject(resource);
      System.out.println("return resource success.."+resource);
  }

}

其StringPool繼承Pool就可以了:

public class StringPool extends Pool{
  public StringPool(){

  }

  public StringPool(final GenericObjectPoolConfig poolConfig,StringFactory factory){
     super(poolConfig,factory); 
  }
}

如下爲獲取資源的實例:

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig ();
        poolConfig.setMaxTotal(10);
        StringFactory factory = new StringFactory();
        StringPool pool =  new StringPool(poolConfig,factory);
        for(int i=0;i<15;i++){
            System.out.println(i+":");
            String str = pool.getResource();
            System.out.println(str);            
        }
        try {
            pool.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

其運行結果如下:
這裏寫圖片描述

測試一下釋放資源的方法:

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig ();
        poolConfig.setMaxTotal(10);
        StringFactory factory = new StringFactory();
        StringPool pool =  new StringPool(poolConfig,factory);
        for(int i=0;i<15;i++){
            System.out.println(i+":");
            String str = pool.getResource();
            System.out.println(str);
            pool.returnResourceObject(str);
        }
        try {
            pool.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

其運行結果如下:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章