在实际工作中,我们经常会用到各种连接池,例如:FTP服务器的连接数有限,需要建立连接池;数据库连接数有限,需要建立连接池。那么我们如何快速实现一个连接池呢?无论是FTP连接池还是数据库连接池,我们都会发现它们都有相同的地方,它们都需要:生命周期管理,连接创建管理等等。如果我们从头开始实现这些功能,那将花费我们很长时间!有没有可以快速实现线程池的通用库?开发了一个公共库:ApacheCommonsPool(以下简称ACP)。本质上,ACP库提供了管理对象池的通用能力,当然也可以用来管理连接池!什么是ACP?ACP库提供了一套完整的对象池API,以及几个Featured对象池实现。目前最常用的版本是2.0版本,相对于1.x版本来说不是简单的升级。2.0版完全重写了对象池实现,显着提高了性能和可扩展性,并包括可靠的实例跟踪和池监控。ApacheCommonsPool的官网地址为:Pool–Overview。如果要搜索相关文献,去这里最权威最全面。如何使用ACP?使用ACP实现线程池,首先需要引入ACP的依赖包。这里我们以Maven为例。org.apache.commonscommons-pool22.0使用ACP实现一个对象池,大致可以是分为三步Step1:Createanobjectfactory:告诉ACP如何创建你想要的对象。创建对象池:告诉ACP你想创建什么样的对象池。使用对象池:ACP告诉您如何使用您的对象。创建对象工厂对象工厂告诉ACP它应该如何创建、激活、停用和销毁您的对象。创建对象工厂非常简单,只需要实现ACP的PooledObjectFactory接口即可。PooledObjectFactory接口的定义如下:)throwsException;voidpassivateObject(PooledObjectp)throwsException;}但更多情况下,我们会继承BasePooledObjectFactory类来实现对象工厂。因为BasePooledObjectFactory类是PooledObjectFactory的基本实现类,使用它可以为我们省去很多麻烦。通过继承这个抽象类,我们只需要实现两个方法:create()和wrap()方法。//告诉ACP如何创建对象publicabstractTcreate()throwsException;//定义你要返回的对象publicabstractPooledObjectwrap(Tobj);create()方法定义了你的对象初始化过程,最后返回初始化后的对象。比如你要定义一个SFTP连接,首先需要定义一个JSch对象,然后设置账号密码,然后连接服务器,最后返回一个ChannelSftp对象。publicChannelSftpcreate(){//SFTP连接创建过程}wrap()方法定义了你要返回的对象。对于一个SFTP连接池,它实际上是一个ChannelSftp对象。通常,您可以改用DefaultPooledObject类。参考实现如下:@OverridepublicPooledObjectwrap(Foofoo){returnnewDefaultPooledObject(foo);}创建对象池创建对象工厂后,ACP已经知道如何创建你需要的对象了。那么接下来,您需要根据自己的实际需要创建一个对象池。在ACP中,我们通过GenericObjectPool和GenericObjectPoolConfig来创建一个对象池。//声明一个对象池privateGenericObjectPoolsftpConnectPool;//设置连接池配置GenericObjectPoolConfigpoolConfig=newGenericObjectPoolConfig();poolConfig.setEvictionPolicyClassName("tech.shuyi.javacodechip.acp.SftpEvictionPolicy");poolConfig.setBlockWhenExhausted.poolConfig(true);setJmxEnabled(false);poolConfig.setMaxWaitMillis(1000*10);poolConfig.setTimeBetweenEvictionRunsMillis(60*1000);poolConfig.setMinEvictableIdleTimeMillis(20*1000);poolConfig.setTestBhileIdle(true);TpoolOnconfig.set.setTest(Test)true);poolConfig.setMaxTotal(3);//设置放弃策略AbandonedConfigabandonedConfig=newAbandonedConfig();abandonedConfig.setRemoveAbandonedOnMaintenance(true);abandonedConfig.setRemoveAbandonedOnBorrow(true);this.sftpConnectPool=newGenericObjectPool<>(sftpConnectfigfactory,abandonedCon在上面的代码中创建SFTP连接池,我们配置了一些线程池参数,设置了丢弃策略,丢弃策略很重要,如果不设置丢弃策略,那么会获取到一个无效的连接,导致获取文件失败。放弃策略是通过poolConfig.setEvictionPolicyClassName设置的,这里我们设置了SftpEvictionPolicy类,代码内容如下:>underTest,intidleCount){try{//连接失败时驱逐if(!underTest.getObject().isConnected()){log.warn("connecttimeout,evicttheconnection.time={}",System.currentTimeMillis()-underTest.getLastReturnTime());returntrue;}}catch(Exceptione){returntrue;}returnfalse;}}看到这里,创建线程池的代码就结束了,SftpConnectPool文件的全部内容如下:@Slf4jpublicclassSftpConnectPool{privateGenericObjectPoolsftpConnectPool;publicSftpConnectPool(SftpConnectFactorysftpConnectFactory){//设置连接池配置GenericObjectPoolConfigpoolConfig=newGenericObjectPoolConfig();poolConfig.setEvictionPolicyClassName("tech.shuyi.javacodechip.acp.SftpEvictionPolicyhen");poolConfig(haustEx)onfig.setJmxEnabled(false);poolConfig.setMaxWaitMillis(1000*10);poolConfig.setTimeBetweenEvictionRunsMillis(60*1000);poolConfig.setMinEvictableIdleTimeMillis(20*1000);poolConfig.setTestWhileIdle(true);setTestOnBorrow(true);poolConfig.setMaxTotal(3);//设置放弃策略AbandonedConfigabandonedConfig=newAbandonedConfig();abandonedConfig.setRemoveAbandonedOnMaintenance(true);abandonedConfig.setRemoveAbandonedOnBorrow(true);this.sftpConnectPool=newGenericObjectPool