オブジェクトプーリング

commons-poolを利用してDBではなく
自作クラスのオブジェクトをプーリングしたい場合には
下記のようにクラスを作成すれば実現できる。


Factoryクラス


/**
*
*/
package main2.pool.factory;

import main2.pool.PooledObject;

import org.apache.commons.pool.PoolableObjectFactory;

/**
* プールされているオブジェクトに対するアクションを実行するクラス
* 2011/09/03
* PoolFactory.java
*/
public class PoolFactory implements PoolableObjectFactory{

/**
* プールするオブジェクトを作成する
* {@inheritDoc}
*/
public Object makeObject() throws Exception {
System.out.println("Call makeObject.");


// プールするオブジェクトのインスタンス生成
return new PooledObject();
}

/**
* オブジェクトを破棄する
* {@inheritDoc}
*/
public void destroyObject(Object obj) throws Exception {
System.out.println("Call destroyObject.");

}

/**
* オブジェクトを検証する
* このインスタンスがプールにて安全に使用できるかを判断します。 このオブジェクトを破棄するべき場合には false
* {@inheritDoc}
*/
public boolean validateObject(Object obj) {
System.out.println("Call validateObject.");

return true;
}

/**
* オブジェクトを再初期化する
* {@inheritDoc}
*/
public void activateObject(Object obj) throws Exception {
System.out.println("Call activateObject.");

}

/**
* プールに戻されたインスタンスの後処理
* {@inheritDoc}
*/
public void passivateObject(Object obj) throws Exception {
System.out.println("Call passivateObject.");

}
}


プーリングに対する操作クラス


/**
*
*/
package main2.pool.controller;

import java.util.NoSuchElementException;

import main2.pool.factory.PoolFactory;

import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool.Config;
import org.apache.commons.pool.impl.GenericObjectPoolFactory;

/**
* 2011/09/03
* PoolingController.java
*/
public class PoolingController<E> {

private ObjectPool pool;

/**
* コンストラク
* プーリングオブジェクトの生成と、パラメータの設定処理。
*/
public PoolingController() {
System.out.println("constractor PoolingController - start");

/**
* パターン1
* GenericObjectPoolFactoryのコンストラクタでパラメータ設定
*/
// コンストラク
// GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle)
GenericObjectPoolFactory factory = new GenericObjectPoolFactory(new PoolFactory(),1);
pool = factory.createPool();

/**
* パターン2
* GenericObjectPoolでパラメータ設定
*/
this.pool = new GenericObjectPool(new PoolFactory());

// 同時にプールから取り出すことのできるオブジェクトの最大数
((GenericObjectPool) pool).setMaxActive(2);

//プール内に保持できる未使用のオブジェクトの最大数
((GenericObjectPool) pool).setMaxIdle(2);

// プール内に存在可能なアイドル接続数の最大数を指定
// 接続切断時、DBCPはこの接続をプール内に溜めようとしますが
// その時プール内にこの数以上の接続が存在した場合、接続は溜められず削除
((GenericObjectPool) pool).setMinIdle(10);

// 接続要求があったときに利用できる接続が存在しない(つまり接続数がmaxActiveに達している)場合
// 利用できるようになるまで待つ時間をミリ秒単位で指定
((GenericObjectPool) pool).setMaxWait(6000);

// borrowObject() メソッドは新たなオブジェクトが利用できるまでまたは 最大待機時間 に達するまで待機
((GenericObjectPool) pool).setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);

/**
* パターン3
* GenericObjectPoolでパラメータ設定(専用のconfigクラス利用)
*/
Config poolsConfig = new Config();
poolsConfig.maxActive = 2;
poolsConfig.maxIdle = 3;
poolsConfig.maxWait = 6000;
poolsConfig.minIdle = 2;
poolsConfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;

this.pool = new GenericObjectPool(new PoolFactory(), poolsConfig);

// borrowObject()する前にPoolFactoryクラスのvalidateObject()を実施しバリデートチェックする
((GenericObjectPool) pool).setTestOnBorrow(false);

// 下記setTestOnReturn()がtrueだとaddObject()がコールされた際にPoolFactoryクラスのvalidateObjectを実施する
// returnObject()する前にvalidateチェックする
((GenericObjectPool) pool).setTestOnReturn(true);

System.out.println("constractor PoolingController - end");

}

/**
* プールから取り出す
* もしオブジェクトがプールされていなければ
* ファクトリのmakeObject()によりオブジェクトが生成される。
* 生成する際にmaxActive、maxIdleなどの数値により生成するかどうか変わる。
* オブジェクトを返却する際にvalidateするかはコンストラクタでおこなっているset~()
* のboolean値により変わる
* @return プールされているオブジェト
*/
public E borrowObject() {
try {
return (E) pool.borrowObject();
} catch(NoSuchElementException e) {
System.out.println("timeout");
//e.printStackTrace();
throw new RuntimeException(e);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

/**
* プールに返却する
* @param obj
*/
public void returnObject(Object obj) {
try {
pool.returnObject(obj);
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* プールにオブジェクトを追加する
*/
public void addObject() {
try {
pool.addObject();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 現在プールから貸し出されているインスタンスの数
*/
public int getNumActive() {
return pool.getNumActive();
}

/**
* 現在プール内にある使用されていないインスタンスの数
*/
public int getNumIdle() {
return pool.getNumIdle();
}

/**
* プールのクリア
*/
public void clear() {
try {
pool.clear();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* プールのクローズ
*/
public void close() {
try {
pool.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}


呼び出すサンプル


PoolingController sample = new PoolingController();
System.out.println("1. borrowObject");

// コントローラからプールされているオブジェクトを取得
Object obj = sample.borrowObject();
System.out.println(obj);
// 現在プールされているオブジェクト数を標準出力
System.out.println("Idle : " + sample.getNumIdle());

System.out.println("addObject");
// プールするオブジェクトの生成とプーリング
sample.addObject();
System.out.println("Idle : " + sample.getNumIdle());

System.out.println("addObject");
sample.addObject();
System.out.println("Idle : " + sample.getNumIdle());
sample.clear();
sample.close();