首頁 > 軟體

利用Apache Common將java物件池化的問題

2022-06-14 14:05:57

什麼是物件池化?

物件被建立後,使用完畢不是立即銷燬回收物件,而是將物件放到一個容器儲存起來,下次使用的時候不用建立物件,而是從容器中直接獲取。

什麼樣的物件需要池化?

一般需要池化的物件往往都是比"重量級"較的物件,建立和銷燬都比較耗時,比如我們的"執行緒","資料庫連結物件","tcp連結物件", "FTP連結物件" 等等。

物件池化的好處?

這些物件池化後,之後使用的時候不用建立,直接使用即可,可以大大縮短程式的執行時間,以及建立物件時對CPU資源的消耗,以及對系統資源的控制(池化的物件數量有限,不會一直建立物件,導致系統資源耗盡,或者造成程式OOM的情況)進而提高系統的穩定性。

物件池化後需要注意什麼?

這些被池化的物件都有一個特點,都是"活的",比如資料庫連結物件內部一般儲存了一個TCP連結,所以,這個物件"能用"的前提是這個TCP連結是有效的,執行緒物件"能用"的前提是執行緒的狀態不是"凋亡"狀態,所以我們有必要定期對物件的"健康狀態"進行檢查,剔除掉"不能用"的物件,並填充新的物件給"物件池"。

使用apache-common-pool池化物件

  • 引入依賴
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.9.0</version>
        </dependency>
  • 需要池化的物件範例
public class Foo {
    private final String username;
    public Foo(String username) {
        this.username = username;
    }
    public String getUsername() {
        return username;
    }
}
  • 構建物件建立工廠

可以直接實現org.apache.commons.pool2.PooledObjectFactory<T>介面實現建立、銷燬、鈍化、取消等介面,也可以使用他的抽象類,實現建立和包裝方法即可。

public class FooPoolObjectFactory extends BasePooledObjectFactory<Foo> {
    @Override
    public Foo create() throws Exception {
        return new Foo(String.valueOf(RandomUtils.randomInt(0, 10)));
    }
    @Override
    public PooledObject<Foo> wrap(Foo obj) {
        return new DefaultPooledObject<>(obj);
    }
}
  • 實現驅逐策略

一般資料庫連結物件,要定期進行心跳,確保連結可用,如果連結斷開,需要銷燬物件,並重新建立新的物件。common-pool中,我們可以實現驅逐策略,對物件進行定期檢查

public class FooEvictionPolicy implements EvictionPolicy<Foo> {
    @Override
    public boolean evict(EvictionConfig config, PooledObject<Foo> underTest, int idleCount) {
        // todo  定期檢查物件某些功能是否可用
        return true;
    }
}
  • 構建&設定物件池
    public GenericObjectPool<Foo> fooGenericObjectPool() {
        GenericObjectPoolConfig<Foo> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setEvictionPolicy(new FooEvictionPolicy());
        poolConfig.setBlockWhenExhausted(true);
        poolConfig.setJmxEnabled(false);
        poolConfig.setMaxWaitMillis(1000 * 10);
        poolConfig.setTimeBetweenEvictionRunsMillis(60 * 1000);
        poolConfig.setMinEvictableIdleTimeMillis(20 * 1000);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setTestOnReturn(true);
        poolConfig.setTestOnBorrow(true);
        poolConfig.setMaxTotal(3);
        // 設定拋棄策略
        AbandonedConfig abandonedConfig = new AbandonedConfig();
        abandonedConfig.setRemoveAbandonedOnMaintenance(true);
        abandonedConfig.setRemoveAbandonedOnBorrow(true);
        return new GenericObjectPool<>(new FooPoolObjectFactory(), poolConfig, abandonedConfig);
    }

如果我們使用的是spring容器,一般我們需要將該物件交由spring管理。

  • 獲取&歸還物件
    private final GenericObjectPool<Foo> fooGenericObjectPool = fooGenericObjectPool();
    public Foo borrowFoo () throws Exception {
        return fooGenericObjectPool.borrowObject();
    }
    public void returnObject(Foo foo){
        fooGenericObjectPool.returnObject(foo);
    }

到此這篇關於利用Apache Common將java物件“池化”的文章就介紹到這了,更多相關Apache Common java物件池化內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com