在实际工作中,我们经常会用到各种连接池,例如:连接 FTP 服务器的连接数有限,需要建立一个连接池;连接数据库的连接数有限,需要建立一个连接池。那我们如何去快速实现一个连接池呢?
无论是 FTP 连接池,还是数据库连接池,我们会发现它们都有相同的地方,它们都需要:生命周期管理、连接创建管理等等。如果我们从零开始去实现这些功能,那我们要耗费的时间就很长了!那有没有一个通用的库可以快速实现一个线程池呢?
得益于 Java 完善的生态,前人们针对这种需要开发了一个通用库:Apache Commons Pool(下文简称 ACP)。本质上来说,ACP 库提供的是管理对象池的通用能力,当然也可以用来管理连接池了!
创作不易,点个赞再看吧!文末有福利记得查看哦~
什么是 ACP?
ACP 库提供了一整套用于实现对象池化的 API,以及若干种各具特色的对象池实现。目前最常用的版本是 2.0 版本,相对于 1.x 版本而言,并不是简单升级。2.0 版本是对象池实现的完全重写,显著地提升了性能和可伸缩性,并且包含可靠的实例跟踪和池监控。
Apache Commons Pool 的官网地址为:Pool – Overview,想翻找相关文档资料,到这里去是最权威、最全面的。
如何使用 ACP?
要使用 ACP 实现一个线程池,首先需要先引入 ACP 的依赖包,这里以 Maven 为例。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.0</version>
</dependency>
要使用 ACP 实现一个对象池,大致可以分为三个步骤:
- 创建对象工厂:告诉 ACP 如何创建你要的对象。
- 创建对象池:告诉 ACP 你想创建一个怎样的对象池。
- 使用对象池:ACP 告诉你如何使用你的对象。
创建对象工厂
对象工厂告诉 ACP,它应该如何去创建、激活、转化、销毁你的对象。创建对象工厂非常简单,只需要实现 ACP 的 PooledObjectFactory 接口即可。PooledObjectFactory 接口的定义如下:
public interface PooledObjectFactory<T> {
PooledObject<T> makeObject() throws Exception;
void destroyObject(PooledObject<T> p) throws Exception;
boolean validateObject(PooledObject<T> p);
void activateObject(PooledObject<T> p) throws Exception;
void passivateObject(PooledObject<T> p) throws Exception;
}
但更多情况下,我们会继承 BasePooledObjectFactory 类来实现对象工厂。因为 BasePooledObjectFactory 类是 PooledObjectFactory 的基础实现类,使用它可以帮我们省了很多麻烦。通过继承这个抽象类,我们只需要实现两个方法:create() 和 wrap() 方法。
// 告诉 ACP 如何创建对象
public abstract T create() throws Exception;
// 定义你要返回的对象
public abstract PooledObject<T> wrap(T obj);
create() 方法定义你的对象初始化过程,最后将初始化完成的对象返回。例如你想定义一个 SFTP 的连接,那么你首先需要定义一个 JSch 对象,之后设置账号密码,之后连接服务器,最后返回一个 ChannelSftp 对象。
public ChannelSftp create