对象池技术是一种常见的对象缓存手段。’对象’意味着池中的内容是一种结构化实体,这也就是一般意义上面向对象中的对象模型;’池’(或动词池化)意味着将有生命周期的对象缓存到’池子’中进行管理,即用即取。缓存的目的大多是为了提升性能,对象池技术的目的也即如此。所以,对象池技术的本质简单来说就是:将具有生命周期的结构化对象缓存到带有一定管理功能的容器中,以提高对象的访问性能。处理网络连接是对象池使用最多的场景。比如一些RPC框架的NettyChannel缓存(如motan),以及数据库连接池的Connection缓存(如DBCP)等。除此之外,我们还可以利用对象池管理一些大对象,这些对象有着相对复杂的构造过程。那么对象池技术与普通的本地缓存(比如guava cache)有什么区别呢?其一,本地cache可能会有一些失效策略,比如按照时间、访问次数等,而对象池是可以没有这些特性的;其二,也是最重要的一点,缓存中的对象是没有一个完整生命周期的概念,而对象池中的对象是具有生命周期的,我们甚至可以对对象的生命周期施加影响。
本篇文章结合了Apache Commons Pool的源代码,讲解了一个通用对象池实现上可能需要考虑的方方面面。在阅读本文之前,我们先思考以下几个问题:
进入池子的对象是什么?需要包装一下吗?池子中的对象可能有一些什么状态和属性呢?池子中的对象可能有哪些组织形式(数据结构)?池子中的对象是怎么创建出来的?我们如何控制池子中的对象(生命周期)?什么时候我们需要校验一个池对象的有效性?什么是eviction?什么是abandon?,区别是什么?如何实现?有哪些对象池接口方法可以提供给用户使用呢?对象被借到的顺序是怎么样的?fifo or lifo?池子中需要定时任务么?定时任务能够做什么?
一个入门的例子
我们先来看官方文档中的一个简单例子,通过这个入门例子让我们对Apache Commons Pool有一个感性的认识,至少我们要知道如何使用这个框架。
不使用对象池
publicclass ReaderUtil { public String readToString(Readerin) throws IOException { // 这里我们构建一个StringBuilder,我们假如他是个大对象,是需要很长时间的创建 Stri