起因

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

最新文章

  1. 4、DES和RSA简介
  2. std::unique_lock&lt;std::mutex&gt; or std::lock_guard&lt;std::mutex&gt; C++11 区别
  3. Max double slice sum 的解法
  4. 在AngularJS中的使用Highcharts图表控件
  5. Ninject之旅之八:Ninject插件模型(附程序下载)
  6. 80端口被占用,pid=4强制杀进程杀不掉
  7. C语言每日一题之No.3
  8. Android IOS WebRTC 音视频开发总结(六六)-- 三个角度分析美女视频直播这个行业
  9. lucene 4.0学习
  10. Qt制作应用插件
  11. CentOS 7安装配置Apache HTTP Server
  12. c# 委托(Func、Action)
  13. C++编译器何时为用户提供默认构造函数
  14. springmvc注解驱动
  15. Ext中defaults与fieldDefaults
  16. sping入门
  17. oracle坏块问题的处理
  18. python2&amp;python3
  19. 用工厂模式解决ASP.NET Core中依赖注入的一个烦恼
  20. 字符串相似度算法(编辑距离Levenshtein Distance)的应用场景

热门文章

  1. 机器学习、深度学习、和AI算法可以在网络安全中做什么?
  2. 如何做好iOS应用安全?这有一把行之有效的“三板斧”
  3. AJPFX的监管与执照
  4. openstack 创建虚拟机的时候报错: Failed to allocate the network(s), not rescheduling.].
  5. leetcode 78. 子集 JAVA
  6. NRF52840相对于之前的NRF52系列、NRF51系列增加了什么功能
  7. iOS-AFNetworking参数和多文件同时上传【多文件上传】
  8. AngularJS自定义Directive
  9. 点击按钮,生成一组一组combobox和slider时,避免控件Id相同,导致控件冲突的方法
  10. h5聊天室web端(仿微博、微信)|h5仿微信网页端|仿微信界面弹窗