GenericObjectPool管理对象池

近日接手一个项目功能的性能优化,该功能主要实现selenium截图。在测试的过程中就发现其创建selenium.WebDriver耗时特别长,于是就想着通过将其对象池化,减少不必要的对象创建/销毁,但是手写管理池比较麻烦,最终采用Apache Commons Pool的GenericObjectPool来实现。

什么是GenericObjectPool?

GenericObjectPool类是Apache Commons Pool库的一部分,用于提供一个通用、高度可配置的对象池实现。它可以很好的控制对象池中对象的数量,一个新的请求如果对象池空,GenericObjectPool会自动的创建新对象。
其核心流程如下:


image.png

创建GenericObjectPool

创建GenericObjectPool的第一步是创建一个BasePooledObjectFactory,这样GenericObjectPool才知道怎么样创建新的对象,理论上,任何对象都可以被池化。

    public static class WebDriverFactory extends BasePooledObjectFactory {
        @Override
        public WebDriver create() {
            // 创建对象
            ChromeOptions options = new ChromeOptions();
            return new ChromeDriver(options);
        }

        @Override
        public PooledObject wrap(WebDriver obj) {
            return new DefaultPooledObject<>(obj);
        }

        @Override
        public boolean validateObject(PooledObject p) {
            // 当需要时在这里实现WebDriver实例的有效性验证
            try {
                p.getObject().getCurrentUrl();  // 尝试获取当前URL
                return true;  // 没有抛出异常,实例有效
            } catch (Exception e) {
                return false;  // 抛出异常,实例无效
            }
        }

        @Override
        public void destroyObject(PooledObject p) {
           // 销毁对象
            p.getObject().quit();
        }
    }

然后,只需要通过这个对象工厂来创建GenericObjectPool:

        // 创建Apache Commons Pool2配置
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMinIdle(minIdle);
        poolConfig.setMaxIdle(maxIdle);
        poolConfig.setMaxTotal(maxTotal);
        poolConfig.setTestOnBorrow(true);
        //poolConfig.setMaxWait(Duration.of(10, ChronoUnit.SECONDS));

        // 创建一个WebDriver工厂,以提供给GenericObjectPool
        WebDriverFactory factory = new WebDriverFactory();

        // 根据我们的配置和工厂创建内部pool
        GenericObjectPool myPool = new GenericObjectPool<>(factory, poolConfig);

它会创建一个新的GenericObjectPool实例,然后使用你的WebDriverFactory实例生成新的对象。

使用GenericObjectPool

一旦有了GenericObjectPool的实例,就可以使用borrowObject方法来获取对象。

WebDriver myObject = null;

try {
    myObject = myPool.borrowObject();
    // 对象使用
} finally {
    myPool.returnObject(myObject);  // 不再需要时,返回对象到池中
}

你可能感兴趣的:(GenericObjectPool管理对象池)