对象池模式是软件开发中广泛使用的设计模式,旨在通过重用创建成本高昂的对象来提高应用程序性能和效率。它在创建对象的新实例非常耗时且对象创建频率很高的情况下特别有用。当可以创建的对象实例数量由于资源限制而受到限制时,此模式也很有用。

工作机制

对象池模式的工作原理是创建一个预初始化对象池,可以根据需要借用和归还这些对象。不是每次需要时都创建一个新对象,而是在池中搜索可以重用的可用对象。如果对象可用,则将其从池中移除并返回给请求对象,否则,将创建一个新对象并将其添加到池中。

image.png

代码实现对象池

我这边通过使用Apache Common Pool来实现对象的池化技术。

1、引入依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.9.0</version>
</dependency>

2、需要池化的对象示例

public class Foo {

    private final String username;

    public Foo(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }
}

3、构建对象创建工厂 可以直接实现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);
    }
}

4、实现驱逐策略。我们有必要定期对对象的"健康状态"进行检查,剔除掉"不能用"的对象,并填充新的对象给"对象池"。一般数据库链接对象,要定期进行心跳,确保连接可用,如果连接断开,需要销毁对象,并重新创建新的对象。common-pool中,我们可以实现驱逐策略,对对象进行定期检查。关注公z号:码猿技术专栏,回复关键词:1111 获取阿里内部性能调优手册

public class FooEvictionPolicy implements EvictionPolicy<Foo> {

    @Override
    public boolean evict(EvictionConfig config, PooledObject<Foo> underTest, int idleCount) {
        // todo  定期检查对象某些功能是否可用
        return true;
    }
}

5、构建&配置对象池

 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);
 }

6、获取&归还对象

private final GenericObjectPool<Foo> fooGenericObjectPool = fooGenericObjectPool();

public Foo borrowFoo () throws Exception {
    return fooGenericObjectPool.borrowObject();
}

public void returnObject(Foo foo){
    fooGenericObjectPool.returnObject(foo);
}

对象池优点