tomcat jdbc数据库连接池详解之PoolCleaner
PoolCleaner是一个定时任务,该任务在创建线程池时自动启动,该任务定期执行哪些工作呢,带着这个问题进入源码:
@Overridepublic void run() {ConnectionPool pool = this.pool.get();if (pool == null) {stopRunning();} else if (!pool.isClosed() &&(System.currentTimeMillis() - lastRun) > sleepTime) {lastRun = System.currentTimeMillis();try {if (pool.getPoolProperties().isRemoveAbandoned())pool.checkAbandoned();if (pool.getPoolProperties().getMinIdle() < pool.idle.size())pool.checkIdle();if (pool.getPoolProperties().isTestWhileIdle())pool.testAllIdle();} catch (Exception x) {log.error("", x);}}}
而checkAbandoned、checkIdle、testAllIdle的执行是受条件约束的,比如checkAbandoned必须在连接池属性removeAbandoned配置为true时才会执行,更多tomcat jdbc连接池配置请参考官网:http://tomcat.apache.org/tomcat-8.5-doc/jdbc-pool.html
下面将一一介绍checkAbandoned、checkIdle、testAllIdle三个任务到底做了些什么工作,
/**checkAbandoned会清除一些使用时间过长的数据库连接,要注意的是这部分工作针对的就是使用中的数据库连接,及ConnectionPool类BlockingQueue<PooledConnection> busy属性!!**/public void checkAbandoned() {try {if (busy.size()==0) return;Iterator<PooledConnection> locked = busy.iterator();int sto = getPoolProperties().getSuspectTimeout();while (locked.hasNext()) {PooledConnection con = locked.next();boolean setToNull = false;try {//操作之前加锁con.lock();//该连接已被移至idle队列中if (idle.contains(con))continue;long time = con.getTimestamp();long now = System.currentTimeMillis();if (shouldAbandon() && (now - time) > con.getAbandonTimeout()) {//从busy队列中移除该连接busy.remove(con);//废弃该连接abandon(con);setToNull = true;} else if (sto > 0 && (now - time) > (sto*1000)) {//将该连接列为疑似要被废弃状态并发送废弃消息suspect(con);} else {//do nothing} //end if} finally {con.unlock();if (setToNull)con = null;}} //while} catch (ConcurrentModificationException e) {log.debug("checkAbandoned failed." ,e);} catch (Exception e) {log.warn("checkAbandoned failed, it will be retried.",e);}}protected boolean shouldAbandon() {if (poolProperties.getAbandonWhenPercentageFull()==0) return true;float used = busy.size();float max = poolProperties.getMaxActive();float perc = poolProperties.getAbandonWhenPercentageFull();return (used/max*100f)>=perc;}
shouldAbandon方法busy状态的连接是否可以被废弃,被废弃需要满足以下条件:
busy态连接数/最大允许存活量>最大允许的存活比例
//该任务针对的是idle队列的连接,即ConnectionPool的BlockingQueue<PooledConnection> idle属性public void checkIdle(boolean ignoreMinSize) {//ignoreMinSize传入值为falsetry {if (idle.size()==0) return;long now = System.currentTimeMillis();Iterator<PooledConnection> unlocked = idle.iterator();//当前idle队列数目大于连接池设置的minIdle值,需要释放多余的空间连接while ( (ignoreMinSize || (idle.size()>=getPoolProperties().getMinIdle())) && unlocked.hasNext()) {PooledConnection con = unlocked.next();boolean setToNull = false;try {con.lock();//the con been taken out, we can't clean it up//idle跟busy队列中数据可以互相转换,到底怎么转换的后期文章将会介绍if (busy.contains(con))continue;long time = con.getTimestamp();//具体看下面的shouldReleaseIdle方法if (shouldReleaseIdle(now, con, time)) {release(con);idle.remove(con);setToNull = true;} else {//do nothing} //end if} finally {con.unlock();if (setToNull)con = null;}} //while} catch (ConcurrentModificationException e) {log.debug("checkIdle failed." ,e);} catch (Exception e) {log.warn("checkIdle failed, it will be retried.",e);}}protected boolean shouldReleaseIdle(long now, PooledConnection con, long time) {if (con.getConnectionVersion() < getPoolVersion()) return true;//getReleaseTime返回的是连接池的minEvictableIdleTimeMillis配置,这个参数决定了一个连接在被废弃前所允许的最大idle时间else return (con.getReleaseTime()>0) && ((now - time) > con.getReleaseTime()) && (getSize()>getPoolProperties().getMinIdle());}
//在空闲期检测所有的idle队列中连接public void testAllIdle() {try {if (idle.size()==0) return;Iterator<PooledConnection> unlocked = idle.iterator();while (unlocked.hasNext()) {PooledConnection con = unlocked.next();try {con.lock();//the con been taken out, we can't clean it upif (busy.contains(con))continue;//如果该连接检验失败则可以从idle队列移除,并释放该数据库连接,由于使用数据库连接池的连接是从idle队列中获取的,为了保证连接的有效性需要定期检测这些连接,有些连接可能会被数据库服务端关闭,如果不校验就使用,很可能会使用到无效的连接!if (!con.validate(PooledConnection.VALIDATE_IDLE)) {idle.remove(con);release(con);}} finally {con.unlock();}} //while} catch (ConcurrentModificationException e) {log.debug("testAllIdle failed." ,e);} catch (Exception e) {log.warn("testAllIdle failed, it will be retried.",e);}}
tomcat jdbc数据库连接池详解之PoolCleaner相关推荐
- JDBC中C3PO数据库连接池详解
-----------------------------------------------------JDBC中C3PO数据库连接池详解------------------------------ ...
- Spring Boot使用hikari、druid、c3p0等数据库连接池详解
文章目录 前言 Hikari连接池 Druid连接池 Druid(新版starter)连接池 C3P0连接池(1 C3P0连接池(2 扩展 前言 截至Spring Boot V2.0为止,官方仅为下列 ...
- Druid 数据库连接池 详解
推荐阅读:JDBC详解 文章目录 概述 数据库连接池实现 Driud使用流程 代码示例 概述 1.数据库连接池是个容器,负责分配.管理数据库连接(Connection): 2.它允许应用程序重复使用一 ...
- 干货 | Tomcat 连接数与线程池详解
转载自 干货 | Tomcat 连接数与线程池详解 前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在 ...
- Tomcat(二):tomcat配置文件server.xml详解和部署简介
1. 入门示例:虚拟主机提供web服务 该示例通过设置虚拟主机来提供web服务,因为是入门示例,所以设置极其简单,只需修改$CATALINA_HOME/conf/server.xml文件为如下内容即可 ...
- JDBC学习笔记01【JDBC快速入门、JDBC各个类详解、JDBC之CRUD练习】
黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...
- JDBC的URL详解
文章目录 JDBC的URL详解 1.jdbc的格式 2.例如: 3.参数详解: JDBC的URL详解 1.jdbc的格式 jdbc:mysql://[host][,failoverhost...][: ...
- Spring Boot 使用 Druid 连接池详解
Spring Boot 使用 Druid 连接池详解 Alibaba Druid 是一个 JDBC 组件库,包含数据库连接池.SQL Parser 等组件,被大量业务和技术产品使用或集成,经历过严苛的 ...
- Spring JDBC数据库连接池设置
对于任何Java应用程序而言, 在Spring框架中设置JDBC数据库连接池都是很容易的,仅需更改spring配置文件中的一些配置即可.使用Apache Commons DBCP和Commons Po ...
- MS SQL Server 数据库连接字符串详解
MS SQL Server 数据库连接字符串详解 问题 : 超时时间已到.在从池中获取连接之前超时时间已过.出现这种情况可能是因为所有池连接都已被使用并已达到最大池大小. 解决办法 1. 在代码里面 ...
最新文章
- mvc-3模型和数据(1)
- Git基础之(二十)——标签管理——创建标签
- 19、HTML文件上传域
- 4-3 数据离散化(无error版本)
- .Net开发环境配置[OS/IIS/VS...]
- IntelliJ IDEA for Mac如何管理SDK/JDK,模块如何设置SDK/JDK?
- clob大数据转换为多行数据
- 【Android自定义控件】圆圈交替,仿progress效果
- pyqt5菜鸟教程_PyQt5教程(一)——第一个PyQt5程序
- SVN汉化包安装后无效果(已解决)
- 实验2-1-2 温度转换 (5 分)
- react 组件 进阶之 ref (ts 版本)
- 使用OpenResty达到十万级并发超高性能Web应用(一):HelloWorld
- 企业网上下单订货管理软件源码搭建功能介绍|移讯云订货通订单管理系统
- flowable 排他网关
- OPPO Pad 2 参数 OPPOPad 2评测怎么样
- Linux / Windows系统中安装最新版 ElasticSearch (es)搜索引擎 超详细图文教程【一看就懂】
- 大山深处的孩子,正在看见更远的星空
- excel的vlookup只匹配出来一部分
- 中国软件行业协会常务副秘书长陈宝国博士带队调研擎天科技