起因

bonecp不具备回缩功能,即连接池持有连接之后,不会主动去释放这些连接(即使这些连接始终处于空闲状态),因此在使用一段时间之后,连接池会达到配置的最大值。

这种方式一定程度上造成了资源的浪费。

改造

参考tomcat-jdbc的策略,每隔一段时间(可配置)会启动定时任务扫描partition中的idle队列,判断idle连接数是否大于partition可持有的最小连接数,如果是,则启动清理方法,将连接释放掉。

为了达到这个目的,实现了ConnectionCleanThread类:

package com.jolbox.bonecp;

import java.sql.SQLException;
import java.util.concurrent.BlockingQueue; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class ConnectionCleanThread implements Runnable { private static final Logger logger = LoggerFactory.getLogger(ConnectionCleanThread.class); private ConnectionPartition partition; private BoneCP pool; protected ConnectionCleanThread(ConnectionPartition connectionPartition, BoneCP pool) {
this.partition = connectionPartition;
this.pool = pool;
} @Override
public void run() {
BlockingQueue freeQueue = null;
ConnectionHandle connection = null;
//获得partition的大小
int partitionSize = this.partition.getAvailableConnections();
for (int i = 0; i < partitionSize; i++) {
//得到free连接的queue
freeQueue = this.partition.getFreeConnections();
//如果空闲连接大于partition的最小允许连接数,回缩到最小允许连接数
while (freeQueue.size() > this.partition.getMinConnections()) {
connection = freeQueue.poll();
connection.lock();
closeConnection(connection);
connection.unlock();
}
}
} /** Closes off this connection
* @param connection to close
*/
private void closeConnection(ConnectionHandle connection) { if (connection != null && !connection.isClosed()) {
try {
connection.internalClose();
} catch (SQLException e) {
logger.error("Destroy connection exception", e);
} finally {
this.pool.postDestroyConnection(connection);
connection.getOriginatingPartition().getPoolWatchThreadSignalQueue().offer(new Object()); // item being pushed is not important.
}
}
} }

同时需要对核心类ConnectionHandle进行改造,加上连接的上锁方法:

protected void lock() {
lock.writeLock().lock();
} protected void unlock() {
lock.writeLock().unlock();
}

在BoneCP类的构造器内加上该线程的定时任务:

/**
* 空闲连接清理任务
*/
private ScheduledExecutorService connectionCleanScheduler; ... this.connectionCleanScheduler = Executors.newScheduledThreadPool(this.config.getPartitionCount(), new CustomThreadFactory("BoneCP-connection-clean-thread"+suffix, true)); ... //定期启动一个线程清理空闲连接
//add 2017-2-10
final Runnable connectionCleaner = new ConnectionCleanThread(connectionPartition, this);
this.connectionCleanScheduler.scheduleAtFixedRate(connectionCleaner, this.config.getConnectionCleanTimeInSeconds(), this.config.getConnectionCleanTimeInSeconds(), TimeUnit.SECONDS);

效果

经过实际测试,可以在后台自动的回收idle连接。

现在只是实现了功能,各种情况暂时没有加入考虑,比如没有判断该连接是否应该被释放。

GitHub地址

bonecp

bonecp回缩功能实现的更多相关文章

  1. DBCP、C3P0、Proxool 、 BoneCP开源连接池的比《转》

     简介   使用评价  项目主页  DBCP DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序用使用 可以设置最大和最小连接,连接等待时 ...

  2. 开源DBCP、C3P0、Proxool 、 BoneCP连接池的比较

    简介 项目主页 使用评价  DBCP DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序用使用 http://homepages.nild ...

  3. BoneCP主要配置参数

    二.BoneCP主要配置参数 1.jdbcUrl 设置数据库URL 2.username 设置数据库用户名 3.password 设置数据库密码 4.partitionCount 设置分区个数.这个参 ...

  4. Druid的简介及功能

    Druid首先是一个数据库连接池.Druid是目前最好的数据库连接池,在功能.性能.扩展性方面,都超过其他数据库连接池,包括DBCP.C3P0.BoneCP.Proxool.JBoss DataSou ...

  5. (转载)DBCP、C3P0、Proxool 、 BoneCP开源连接池的比较

    原文链接: http://blog.csdn.net/miclung/article/details/7231553    简介   使用评价  项目主页  DBCP DBCP是一个依赖Jakarta ...

  6. Druid、BoneCP、DBCP、C3P0等主流数据库对比

    关键功能 Druid BoneCP DBCP C3P0 Proxool JBoss LRU 是 否 是 否 是 是 PSCache 是 是 是 是 否 是 PSCache-Oracle-Optimiz ...

  7. 主流Java数据库连接池分析(C3P0,DBCP,TomcatPool,BoneCP,Druid)

    主流数据库连接池 常用的主流开源数据库连接池有C3P0.DBCP.Tomcat Jdbc Pool.BoneCP.Druid等 C3p0: 开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDB ...

  8. jdbc(1)(三)DBCP、C3P0、Proxool 、 BoneCP开源连接池的简介

     简介          使用评价  项目主页  DBCP DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序用使用 可以设置最大和最小连 ...

  9. [java]BoneCP 参数详解

    BoneCP 参数详解: ======================================== 一.BoneCP配置文件格式(bonecp-config.xml):  xml versio ...

随机推荐

  1. HttpWebRequest和WebClient的用法

    //通过web方式,从远程服务器端下载文件: public static void DownLoad(string Url, string FileName, string machinetype) ...

  2. 用MVC5+EF6+WebApi 做一个考试功能(六) 仓储模式 打造EF通用仓储类

    前言 年底工作比较忙,年度总结还没写,项目要上线,回老家过年各种准备.尤其是给长辈给侄子侄女准备礼物头都大了. 原来想年前先出一版能用的,我看有点悬了,尽量先把大体功能弄出来,扔掉一些,保证能考试,然 ...

  3. C#默认以管理员身份运行程序实现代码

    using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; names ...

  4. Day 42 协程. IO 并发

    一.什么是协程? 是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 协程相比于线程切换效率更快了. ...

  5. Day 5 字典的操作

    1. 例子 ,务必理解 dic = { 'name':'金鑫', 'name_list':[1,2,3,'李杰'], 1:{ 'python10':['小黑','萌哥'], '老男孩':{'name' ...

  6. 201621123018《Java程序设计》第1周学习报告

    1.<Java程序设计>第1周学习报告 1.本周学习报告 关键字:Java的发展.Java语言的特点.JDK.JRE.JVE.Java开发工具.Java环境配置.Java是一种面向对象的程 ...

  7. Codeforces Round #439 (Div. 2) A B C

    强哉qls,这场div2竟是其出的!!! A. The Artful Expedient 暴力 ^ ,判断是否出现,有大佬根据亦或的性质推出 Karen 必赢,太强啦23333333333333. # ...

  8. day 50 AJAX 初入门

    前情提要: jq 学不好,ajax   难用好, 食用先请先确保最起码的jq 能会用 https://www.cnblogs.com/baili-luoyun/p/10473518.html  jq ...

  9. iOS 设置textfield的最大文本长度

    //在现实开发中  需要控制文本输入长度 并实时做短信验证,代码如下 [self.textField addTarget:self action:@selector(codeChange:) forC ...

  10. Swift 使用 #warning

    swift 中没法使用#Warning来提示警告, 可以通过给TODO: FIXME:加上警告, 实现类似的效果. Build Phases ---> Run Script ---> ad ...