物件池commons-pool2的原理與應用
阿新 • • 發佈:2019-01-06
依賴必不可少
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
建立連線池物件
建立一個連線池物件的構造方法需要兩個核心類,GenericObjectPoolConfig類和PooledObjectFactory介面的實現,前者用於存放物件池的配置資訊,後者用於管理存在物件池中的“池化物件”。
1)MyPoolConfig.java,其中一些常用的屬性已經添加了註釋
public class MyPoolConfig extends GenericObjectPoolConfig { public MyPoolConfig(){ setLifo(true); //池用佇列儲存物件,true表示fifo,false表示filo,預設true setFairness(true); //是否使用公平鎖,預設true setMaxWaitMillis(-1);//設定獲取空閒物件的最長等待時間,<0則一直等待,>0則等待一段時間後丟擲NoSuchElementException異常,預設值-1 setMinEvictableIdleTimeMillis(60000); //空閒物件在redis裡超過這個時間就會被移除,預設30分鐘 setTestOnCreate(false);//在建立物件時檢測物件是否有效,true是,預設值是false。 setTestOnBorrow(false); //在從物件池獲取物件時是否檢測物件有效,true是;預設值是false。 setTestOnReturn(false); //在向物件池中歸還物件時是否檢測物件有效,true是,預設值是false。 setTestWhileIdle(true); //在檢測空閒物件執行緒檢測到物件不需要移除時,是否檢測物件的有效性。true是,預設值是false。 setTimeBetweenEvictionRunsMillis(30000); //每隔多長時間執行一次物件空閒檢測執行緒 setBlockWhenExhausted(true); //當物件池沒有空閒物件時,獲取物件的操作是否會被阻塞,預設true setMaxIdle(8); //物件池中最大物件空閒個數 setMaxTotal(8); //物件池中最大物件管理個數 setMinIdle(0); //物件池中最小物件空閒個數 } }
2)MyPooledObjectFactory.java 由於pooledObjectFactory用於管理池化的物件,需要怎麼管理都是我們自己定的,所以我們需要自己實現一個池化物件管理factory,MyPooledObjectFactory。
import com.liantong.entity.Zhang; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 用於我們自己管理池化物件 */ public class MysPooledObjectFactory implements PooledObjectFactory { private Logger logger = LoggerFactory.getLogger(MyJedisPooledObjectFactory.class); /** * 這個方法是用來建立一個物件 * 當在GenericObjectPool類中呼叫borrowObject方法時,如果當前物件池中沒有空閒的物件,GenericObjectPool會呼叫這個方法, * 建立一個物件,並把這個物件封裝到PooledObject類中,並交給物件池管理。 */ @Override public PooledObject makeObject() throws Exception { System.out.println("make object...."); Zhang zhang = new Zhang("110"); DefaultPooledObject<Zhang> zhangDefaultPooledObject = new DefaultPooledObject<>(zhang); return zhangDefaultPooledObject; } /** * 銷燬物件 * 當物件池檢測到某個物件的空閒時間(idle)超時,或使用完物件歸還到物件池之前被檢測到物件已經無效時, * 就會呼叫這個方法銷燬物件。物件的銷燬一般和業務相關,但必須明確的是,當呼叫這個方法之後,物件的生命週期必須結果。 * 如果是物件是執行緒,執行緒必須已結束,如果是socket,socket必須已close,如果是檔案操作,檔案資料必須已flush,且檔案正常關閉。 */ @Override public void destroyObject(PooledObject p) throws Exception { System.out.println("destroy object...."); Object object = p.getObject(); object = null; } /** * 檢測一個物件是否有效 * 在物件池中的物件必須是有效的,這個有效的概念是,從物件池中拿出的物件是可用的。 * 比如,如果是socket,那麼必須保證socket是連線可用的。 * 在從物件池獲取物件或歸還物件到物件池時,會呼叫這個方法,判斷物件是否有效,如果無效就會銷燬。 */ @Override public boolean validateObject(PooledObject p) { System.out.println("validate object"); if (p.getObject()==null) { return false; }else{ return true; } } /** * 啟用一個物件或者說啟動物件的某些操作 * 比如,如果物件是socket,如果socket沒有連線,或意外斷開了,可以在這裡啟動socket的連線。 * 它會在檢測空閒物件的時候,如果設定了測試空閒物件是否可以用testwhileidle,就會呼叫這個方法,在borrowObject的時候也會呼叫。 * 另外,如果物件是一個包含引數的物件,可以在這裡進行初始化。讓使用者感覺這是一個新建立的物件一樣。 */ @Override public void activateObject(PooledObject p) throws Exception { System.out.println("activate object"); } /** * 鈍化一個物件。在向物件池歸還一個物件是會呼叫這個方法。這裡可以對物件做一些清理操作。 * 比如清理掉過期的資料,下次獲得物件時,不受舊資料的影響。 */ @Override public void passivateObject(PooledObject p) throws Exception { System.out.println("passivte object"); } }
建立需要被池化的物件
public class Zhang {
private String accNbr;
public Zhang(String accNbr){
this.accNbr = accNbr;
}
public String getAccNbr() {
return accNbr;
}
public void setAccNbr(String accNbr) {
this.accNbr = accNbr == null ? null : accNbr.trim();
}
}
編寫測試類
public class TestClass {
@Test
public void testRedisA() {
MyPooledObjectFactory myJedisPooledObjectFactory = new MyPooledObjectFactory();
MyPoolConfig myJedisPoolConfig = new MyPoolConfig();
GenericObjectPool<Zhang> genericObjectPool = new GenericObjectPool<Zhang>(myPooledObjectFactory,myPoolConfig);
try {
for(int i=0; i<3; i++) {
Thread.sleep(1000);
//獲取資源物件
Zhang user = genericObjectPool.borrowObject();
//將獲取的資源物件,返還給資源池
genericObjectPool.returnObject(user);
//輸出資源物件
System.out.println(JSON.toJSONString(user));
System.out.println();
}
}catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
輸出結果為
make object....
activate object
passivte object
{"accNbr":"110"}
activate object
passivte object
{"accNbr":"110"}
activate object
passivte object
{"accNbr":"110"}