對這文章發表回應
發表限制: 非會員 可以發表
發表者: 冷日 發表時間: 2008/3/18 6:52:46
SECTION 01 什麼是 Pool
我們常常會聽到 xxx-pooling, 到底什麼是 pool, 簡單來說, 就是先建立一些存在的 object, 放在 pool 之中, 當你有需要的時候, 可以由 pool 中直接抓取, 不需要重新建立.. 最常聽到的就是 database connection pooling, 因為建立資料庫連結是一件耗時的工作, 如果我們先把連結建立好, 就可以節省這一些時間.
SECTION 02 Commons-Pool
Jakarta Commons-Pool 提供了 Pool 的 API 主要有三個
提供一般性的物件 pool 介面, 可以簡單地去使用和實作.
提供小工具可以建立模組化的 pool.
實作出一些通用性的 pool.
目前版本是 1.0.1 , 可以從 <a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-pool/v1.0.1/" target="_blank">此處下載</a>.
SECTION 03 org.apache.commons.pool.*
其實, 要實作 commons-pool 是蠻簡單的一件事情, 在 org.apache.commons.pool 定義了兩種 pool 的模式, 一為 ObjectPool, 另外一個為 KeyedObjectPool , 差異就在取得的時候, 是否可以依照輸入的 key 來索引 Pool 的 Object.
ObjectPool
KeyedObjectPool
在 org.apache.commons.pool 也實作了 BaseObjectPool, BaseKeyedObjectPool 這兩種抽象類別, 可以繼承之繼續開發.
PoolableObjectFactory & KeyedPoolableObjectFactory 就是定義了 Pool 中會用到的 makeObject(), destroyObject(), validateObject(), activateObject() 及 passivateObject(), 而 BasePoolableObjectFactory 及 BaseKeyedPoolableObjectFactory 都是實作 Poolable 的 interface 的.
SECTION 04 org.apache.commons.pool.impl 實作
目前 commons-pool 提供了三種 pool 實作的範本, 當然, 你也可以自行 implements pool interface.
StackObjectPool 提供有限的 idle 數量.
GenericObjectPool 提供各式各樣的設定方式, 包含了設定 idle, active 的數量, 進而回收到 pool 中的設定.
SoftReferenceObjectPool 將會依照需要而變化, 不過是透過 Garbage collector 自動回收.
SECTION 05 Pool 範例 ( 取自 commons-pool 網站 )
ReaderUtil.java
我們把他改成是先取得 pool, 再由 pool 去取值
當然我們可以針對 StringBuffer 做 pool, 雖然這不是個好例子, 不過可以讓大家更簡單地熟悉實作的方式.
StringBufferFactory.java
修改 ReaderUtil 由 StringBufferFactory Pool 得到 StringBuffer.
SECTION 06 結論
我們通常會在 io 的部分採用 pool 機制, 減少一些建立存取的時間, 當然, 對於最耗時的資料庫存取, 更是相對的重要, 未來將會介紹 commons-dbcp ( Database Connection Pooling ) 的專案, 也是實作 commons-pool 的介面.
我們常常會聽到 xxx-pooling, 到底什麼是 pool, 簡單來說, 就是先建立一些存在的 object, 放在 pool 之中, 當你有需要的時候, 可以由 pool 中直接抓取, 不需要重新建立.. 最常聽到的就是 database connection pooling, 因為建立資料庫連結是一件耗時的工作, 如果我們先把連結建立好, 就可以節省這一些時間.
SECTION 02 Commons-Pool
Jakarta Commons-Pool 提供了 Pool 的 API 主要有三個
提供一般性的物件 pool 介面, 可以簡單地去使用和實作.
提供小工具可以建立模組化的 pool.
實作出一些通用性的 pool.
目前版本是 1.0.1 , 可以從 <a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-pool/v1.0.1/" target="_blank">此處下載</a>.
SECTION 03 org.apache.commons.pool.*
其實, 要實作 commons-pool 是蠻簡單的一件事情, 在 org.apache.commons.pool 定義了兩種 pool 的模式, 一為 ObjectPool, 另外一個為 KeyedObjectPool , 差異就在取得的時候, 是否可以依照輸入的 key 來索引 Pool 的 Object.
ObjectPool
Object obj = null;
try {
obj = pool.borrowObject();
//...use the object...
} catch(Exception e) {
//...handle any exceptions...
} finally {
// make sure the object is returned to the pool
if(null != obj) {
pool.returnObject(obj);
}
KeyedObjectPool
Object obj = null;
Object key = "Key";
try {
obj = pool.borrowObject(key);
//...use the object...
} catch(Exception e) {
//...handle any exceptions...
} finally {
// make sure the object is returned to the pool
if(null != obj) {
pool.returnObject(key,obj);
}
}
在 org.apache.commons.pool 也實作了 BaseObjectPool, BaseKeyedObjectPool 這兩種抽象類別, 可以繼承之繼續開發.
PoolableObjectFactory & KeyedPoolableObjectFactory 就是定義了 Pool 中會用到的 makeObject(), destroyObject(), validateObject(), activateObject() 及 passivateObject(), 而 BasePoolableObjectFactory 及 BaseKeyedPoolableObjectFactory 都是實作 Poolable 的 interface 的.
SECTION 04 org.apache.commons.pool.impl 實作
目前 commons-pool 提供了三種 pool 實作的範本, 當然, 你也可以自行 implements pool interface.
StackObjectPool 提供有限的 idle 數量.
GenericObjectPool 提供各式各樣的設定方式, 包含了設定 idle, active 的數量, 進而回收到 pool 中的設定.
SoftReferenceObjectPool 將會依照需要而變化, 不過是透過 Garbage collector 自動回收.
SECTION 05 Pool 範例 ( 取自 commons-pool 網站 )
ReaderUtil.java
import java.io.Reader;
import java.io.IOException;
public class ReaderUtil {
public ReaderUtil() {
}
/**
* Dumps the contents of the {@link Reader} to a
* String, closing the {@link Reader} when done.
*/
public String readToString(Reader in) throws IOException {
StringBuffer buf = new StringBuffer();
try {
for( int c = in.read(); c != -1; c = in.read()) {
buf.append((char)c);
}
return buf.toString();
} catch(IOException e) {
throw e;
} finally {
try {
in.close();
} catch (Exception e) {
// ignored
}
}
}
我們把他改成是先取得 pool, 再由 pool 去取值
import org.apache.commons.pool.ObjectPool;
import java.io.Reader;
import java.io.IOException;
public class ReaderUtil {
private ObjectPool pool;
public ReaderUtil(ObjectPool pool) {
this.pool = pool;
}
/**
* Dumps the contents of the {@link Reader} to a
* String, closing the {@link Reader} when done.
*/
public String readToString(Reader in) throws IOException {
StringBuffer buf = null;
try {
buf = (StringBuffer)(pool.borrowObject());
for(int c = in.read(); c != -1; c = in.read()) {
buf.append((char)c);
return buf.toString();
} catch(IOException e) {
throw e;
} catch(Exception e) {
throw new RuntimeException("Unable to borrow buffer from pool" +
e.toString());
} finally {
try {
in.close();
} catch(Exception e) {
// ignored
}
try {
if(null != buf) {
pool.returnObject(buf);
}
} catch(Exception e) {
// ignored
}
}
}
當然我們可以針對 StringBuffer 做 pool, 雖然這不是個好例子, 不過可以讓大家更簡單地熟悉實作的方式.
StringBufferFactory.java
import org.apache.commons.pool.BasePoolableObjectFactory;
public class StringBufferFactory extends BasePoolableObjectFactory {
// for makeObject we'll simply return a new buffer
public Object makeObject() {
return new StringBuffer();
}
// when an object is returned to the pool,
// we'll clear it out
public void passivateObject(Object obj) {
StringBuffer buf = (StringBuffer)obj;
buf.setLength(0);
}
// for all other methods, the no-op
// implementation in BasePoolableObjectFactory
// will suffice
}
修改 ReaderUtil 由 StringBufferFactory Pool 得到 StringBuffer.
new ReaderUtil(new StackObjectPool(new StringBufferFactory()))
SECTION 06 結論
我們通常會在 io 的部分採用 pool 機制, 減少一些建立存取的時間, 當然, 對於最耗時的資料庫存取, 更是相對的重要, 未來將會介紹 commons-dbcp ( Database Connection Pooling ) 的專案, 也是實作 commons-pool 的介面.