commons-pool2对象池的简单测试

144 阅读2分钟

这里以commons-pool2来进行测试,它的本质是使用阻塞队列 class LinkedBlockingDeque extends AbstractQueue implements Deque, Serializable 来管理空闲对象。这个队列支持线程安全的入队和出队操作,确保在多线程环境下对象的取用和归还是同步的

    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>2.12.0</version>
    </dependency>
public class User {
    private String name;
    private int age;
    private String address;
}
public static ObjectPool<User> getObjectPool() {
        GenericObjectPoolConfig<User> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(10); // 最大对象数
        config.setMaxIdle(5); // 最大空闲对象数
        config.setMinIdle(2); // 最小空闲对象数
        config.setTestOnBorrow(true); // borrow 对象时进行检测
        config.setTestOnReturn(true); // return 对象时进行检测
        config.setTestWhileIdle(true); // 空闲时进行检测
        BasePooledObjectFactory<User> factory = new BasePooledObjectFactory<User>() {
            @Override
            public User create() throws Exception {
                return new User();
            }

            @Override
            public PooledObject<User> wrap(User user) {
                return new DefaultPooledObject<>(user);
            }

            @Override
            public boolean validateObject(PooledObject<User> p) {
                return true;
            }

            @Override
            public void destroyObject(PooledObject<User> p) {
                System.err.println("destroy");
            }
        };

        return new GenericObjectPool<>(factory, config);
    }

第一次对比

        
            User user = pool.borrowObject();
            user.setName(name);
            user.setAge(age);
            user.setAddress(address);
            pool.returnObject(user);
        
            new User(name, age, address);

输出如下, 可以发现, 直接new的快很多。

49696300
2989000

第二次对比

在User中增加

byte[] bytes = new byte[100 * 1024 * 1024];

这样分配对象的时候,成本就比较大了。

public class User {
    private String name;
    private int age;
    private String address;
    byte[] bytes = new byte[100 * 1024 * 1024];
}

从输出结果看,对象池的优势体现的很明显。

65196800
54310277000

对象池 f96c6c4c4aaae58625519323df3a0cd.png 非池 5d24f7e5b9ed5594073d105e65d4422.png

使用 Apache Commons Pool 管理对象池时,并不一定总是比直接使用 new 关键字创建对象来得快。性能的比较取决于多种因素,包括对象的创建成本、池的配置、系统当前的负载情况以及对象的使用模式。 对象池的主要优势在于复用已经创建的对象,减少创建和销毁对象的开销,特别是在对象初始化需要消耗较多资源或时间的情况下(例如数据库连接、线程、网络连接等)。对象池通过减少这些操作,可以提高应用程序的响应速度和吞吐量,同时也减轻垃圾回收的压力。 然而,如果对象的创建成本很低,或者对象池的配置不合理(例如池太小,导致频繁的等待和上下文切换),那么直接创建新对象可能会更快。此外,如果对象池中的所有对象都处于使用中,那么请求对象时仍然需要等待新对象的创建。