作者 | 乔宇
![640?wx_fmt=jpeg](https://i-blog.csdnimg.cn/blog_migrate/2138250af4ff305ed6b4a509738202f1.jpeg)
杏仁后端工程师,关注服务端技术。
我们系统中一般都会存在很多可重用并长期使用的对象,比如线程、TCP 连接、数据库连接等。虽然我们可以简单的在使用这些对象时进行创建、使用结束后销毁,但初始化和销毁对象的操作会造成一些资源消耗。我们可以使用对象池将这些对象集中管理,减少对象初始化和销毁的次数以节约资源消耗。
顾名思义,对象池简单来说就是存放对象的池子,可以存放任何对象,并对这些对象进行管理。它的优点就是可以复用池中的对象,避免了分配内存和创建堆中对象的开销;避免了释放内存和销毁堆中对象的开销,进而减少垃圾收集器的负担;避免内存抖动,不必重复初始化对象状态。对于构造和销毁比较耗时的对象来说非常合适。
当然,我们可以自己去实现一个对象池,不过要实现的比较完善还是要花上不少精力的。所幸的是, Apache 提供了一个通用的对象池技术的实现: Common Pool2,可以很方便的实现自己需要的对象池。Jedis 的内部对象池就是基于 Common Pool2 实现的。
核心接口
Common Pool2 的核心部分比较简单,围绕着三个基础接口和相关的实现类来实现:
ObjectPool
:对象池,持有对象并提供取/还等方法。PooledObjectFactory
:对象工厂,提供对象的创建、初始化、销毁等操作,由 Pool 调用。一般需要使用者自己实现这些操作。PooledObject
:池化对象,对池中对象的封装,封装对象的状态和一些其他信息。
Common Pool2 提供的最基本的实现就是由 Factory 创建对象并使用PooledObject
封装对象放入 Pool 中。
对象池实现
对象池有两个基础的接口 ObjectPool
和 KeyedObjectPool
, 持有的对象都是由 PooledObject
封装的池化对象。 KeyedObjectPool
的区别在于其是用键值对的方式维护对象。
ObjectPool
和 KeyedObjectPool
分别有一个默认的实现类GenericObjectPool
和 GenericKeyedObjectPool
可以直接使用,他们的公共部分和配置被抽取到了 BaseGenericObjectPool
中。
SoftReferenceObjectPool
是一个比较特殊的实现,在这个对象池实现中,每个对象都会被包装到一个SoftReference中。SoftReference允许垃圾回收机制在需要释放内存时回收对象池中的对象,可以避免一些内存泄露的问题。
ObjectPool
下面简单介绍一下 ObjectPool
接口的核心方法,KeyedObjectPool
和ObjectPool
类似,区别在于方法多了个参数: K key
。
public interface ObjectPool<T> {