Object Pooling

オブジェクトのプーリングは
パフォーマンス向上が目的
プーリングとは
生成したオブジェクトをプール(pool)に蓄積しておき 必要になった際にプールからオブジェクトを取り出して利用し 不要になった際にはオブジェクトをプールに戻すこと
利用する度にオブジェクトを生成する方法に比べ 速度が速いのが利点
サーバサイドプログラミングであれば
スレッドオブジェクトやデータベースコネクションオブジェクトなどの生成にオーバーヘッドがかかるオブジェクトをプールして再利用するが一般的


Jakarta CommonsのPoolコンポーネントは
オブジェクトをプールするためのメカニズムを提供するもの

org.apache.commons.pool.ObjectPoolインターフェイス
オブジェクトプールインスタンスを利用するためのインターフェイス
org.apache.commons.pool.PoolableObjectFactoryインターフェイス
オブジェクトプールに蓄積するオブジェクトのライフサイクルを管理するためのインターフェイス

Poolでオブジェクトプールを実現するには
通常まずプールするオブジェクトのライフサイクルを管理する PoolableObjectFactoryインターフェイスの実装クラスを準備する
次にPoolableObjectFactoryインターフェイスの実装クラスをコンストラクタに与えてObjectPoolインターフェイスの実装クラスのインスタンスを生成する
後は生成したObjectPoolインスタンスからオブジェクトを取り出して利用し、不要になった時点でObjectPoolインスタンスにオブジェクトを返す要領

ObjectPoolのメソッドのうち必須なのが
borrowObject(プールからオブジェクトを取り出す)
returnObject(プールから取り出したオブジェクトを返却する)
close(プールをクローズする)
の3つ

ObjectPool#borrowObject()メソッドは
引数なしでオブジェクトをプールから取り出す
単にプーリングするのではなく
あるキーとオブジェクトを結び付けて管理したい場合は
ObjectPoolの代わりにKeyedObjectPoolインターフェイス(org.apache.commons.pool.KeyedObjectPool)の実装クラスを用いる
KeyedObjectPoolインターフェイスのjava.lang.Objectクラスのオブジェクトを引数に持つ borrowObject()メソッドでキーを指定してオブジェクトをプールから取り出せる

Poolには
ObjectPoolの実装クラスとして
org.apache.commons.pool.impl.GenericObjectPool
org.apache.commons.pool.impl.StackObjectPool
org.apache.commons.pool.impl.SoftReferenceObjectPool
の3つが用意されている
※これらに対応するKeyedObjectPoolの実装クラスもある
※ObjectPoolの実装クラスを独自に作成する場合はorg.apache.commons.pool.BaseObjectPool.BaseObjectPoolクラスのサブクラスとして作成することが推奨されている

GenericObjectPool
汎用的なオブジェクトプール
StackObjectPool
限定された個数のオブジェクトをプールするようなオブジェクトプール
ただしアイドル状態のオブジェクトがないときにオブジェクトの取り出し要求がきた場合には新規にオブジェクトを生成する
SoftReferenceObjectPool
アイドル状態のインスタンスが適宜ガベージコレクタによって除去されるようなオブジェクトプール

PoolableObjectFactory
オブジェクトプールがオブジェクトのライフサイクルを管理するためのインタフェース
ObjectPoolの実装クラスのPoolableObjectFactoryオブジェクトを引数に取るコンストラクタに渡すPoolableObjectFactoryでオブジェクトを管理する
※KeyedObjectPoolの実装クラスのコンストラクタにはorg.apache.commons.pool.KeyedPoolableObjectFactoryのオブジェクトを指定する

PoolableObjectFactoryインターフェイスのメソッド
makeObject
オブジェクトを新規に生成する
activateObject
オブジェクトがプールから取り出される前に呼ばれる
passivateObject
オブジェクトがプールに返却されたときに呼ばれる
validateObject
プールから取り出されるオブジェクトが正当であるかどうかを判定する
destroyObject
プールからオブジェクトが破棄されるときに呼ばれる

PoolableObjectFactoryの実装クラスの作成を簡便化するための基底クラスとして
org.apache.commons.pool.BasePoolableObjectFactoryがある



DBアクセス用のJDBCドライバが生成するjava.sql.Connectionをプーリングして再利用する

1. Connectionオブジェクトの取得
2. SQL文の発行(SELECT 1)
3. Connectionオブジェクトの解放

1.
. try {
.  // MySQLのためのJDBCドライバのロード
.  Class.forName("com.mysql.jdbc.Driver");
.  // オブジェクトプールの管理クラスのインスタンス生成
.  PoolableObjectFactory factory = new SimpleConnectionFactory(url_, user_, password_);
.  // オブジェクトプールのインスタンス生成
.  pool_ = new StackObjectPool(factory);
. } catch (Throwable t) {
.  throw new RuntimeException(t);
. }

オブジェクトプールを利用するための
プーリングするオブジェクトのライフサイクルを管理するPoolableObjectFactoryの実装クラスを用意する

SimpleConnectionFactory.java(抜粋)
.public class SimpleConnectionFactory extends BasePoolableObjectFactory{
... (略) ...
. /**
.  * このクラスのインスタンスを生成する。
.  *
.  * @param url データベース接続のためのURL。
.  * @param user データベース接続のためのユーザ名。
.  * @param password データベース接続のためのパスワード。
.  */
. public SimpleConnectionFactory(String url, String user, String password) {
.  url_ = url;
.  user_ = user;
.  password_ = password;
. }
.
. /**
.  * java.sql.Connectionオブジェクトを生成する。
.  *
.  * @return 生成したオブジェクト。
.  */
. public Object makeObject() throws Exception {
.  return DriverManager.getConnection(url_, user_, password_);
. }
.}

生成したConnectionFactoryインスタンスをコンストラクタ引数にObjectPoolのインスタンスを生成する

※ファクトリクラスを用いてオブジェクトプールのインスタンス生成するも可
StackObjectPoolであればorg.apache.commons.pool.impl.StackObjectPoolFactory で生成する具合


プールしてるオブジェクトの取得
. Connection con = null;
. for (int i = 0; i < count; i++) {
.  try {
.   // Connectionオブジェクトの取得
.   con = getConnection(usePool);
.   // SQL文の実行
.   Statement stmt = con.createStatement();
.   ResultSet rs = stmt.executeQuery("SELECT 1");
.   rs.close();
.   stmt.close();
.  } finally {
.   // Connectionオブジェクトの返却
.   returnConnection(con, usePool);
.  }
. }

getConnection()とreturnConnection()
. /**
.  * java.sql.Connectionオブジェクトを返す。
.  *
.  * @param usePool trueの時プールからオブジェクトを取得して返す。
.  * falseの時オブジェクトを毎回生成して返す。
.  * @return java.sql.Connectionオブジェクト。
.  */
. private Connection getConnection(boolean usePool) throws Exception {
.  if (usePool) {
.   // オブジェクトプールからオブジェクトを取り出す
.   return (Connection)pool_.borrowObject();
.  }
.  return DriverManager.getConnection(url_, user_, password_);
. }

. /**
.  * java.sql.Connectionオブジェクトの使用を終了する。
.  *
.  * @param con java.sql.Connectionオブジェクト。
.  * @param usePool trueの時オブジェクトをプールに返却する。
.  * falseの時オブジェクトをクローズする。
.  */
. private void returnConnection(Connection con, boolean usePool) throws Exception {
.  if (con != null) {
.   if (usePool) {
.    // オブジェクトプールにオブジェクトを返却する
.    pool_.returnObject(con);
.   } else {
.    con.close();
.   }
.  }
. }

必要な初期化処理や終了処理は通常PoolableObjectFactoryクラスが行うので
プールから取り出したオブジェクトに対するConnectionオブジェクトの初期化や
プールに返却するオブジェクトに対するConnectionオブジェクトのクローズ処理は不要

ref:
横田健彦, 第5回Commonsでオブジェクトプーリングを実現, 2003/4/12
http://www.atmarkit.co.jp/fjava/rensai2/jakarta05/jakarta05.html

tag : PoolableObjectFactory

2010-03-04 01:06 : __lang__java : コメント : 0 : トラックバック : 0 :
コメントの投稿
非公開コメント

« next  ホーム  prev »

search

ad



counter


tag cloud

category cloud