所属文章:池化技术(一)Druid是如何管理数据库连接的?

本代码段对应主流程1,具体用来获取一个连接:


lic DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException {
init(); //初始化,即主流程2 if (filters.size() > 0) {
FilterChainImpl filterChain = new FilterChainImpl(this); //责任链,内部也是触发下面的getConnectionDirect方法,只是要走一遍责任链上每个filter的逻辑,这里不做描述,后续放到流程1.1里体现
return filterChain.dataSource_connect(this, maxWaitMillis);
} else {
return getConnectionDirect(maxWaitMillis); //触发getConnectionDirect
}
} public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
int notFullTimeoutRetryCnt = 0;
for (;;) { //死循环
/**
* 真正返回出去的连接对象,注意这里是被druid包装成了DruidPooledConnection类型,
* 实际上池子里存放的连接类型是DruidConnectionHolder,DruidPooledConnection类本身持有一个holder属性,
* 用于保存真正的连接对象,而DruidConnectionHolder才是真正保存驱动连接对象的类。
*/
DruidPooledConnection poolableConnection;
try {
poolableConnection = getConnectionInternal(maxWaitMillis); //从池子里获取连接,这一个后续放到流程1.2体现
} catch (GetConnectionTimeoutException ex) {
if (notFullTimeoutRetryCnt <= this.notFullTimeoutRetryCount && !isFull()) { //出现了超时异常,在连接池没满且重试次数未超过上限的情况下,重试一次(notFullTimeoutRetryCount默认是0,所以至少可以重试一次)。
notFullTimeoutRetryCnt++; //重试次数+1
if (LOG.isWarnEnabled()) {
LOG.warn("get connection timeout retry : " + notFullTimeoutRetryCnt);
}
continue;
}
throw ex; //超过重试次数或者池子已满仍然获取失败,则直接抛出异常
} if (testOnBorrow) { //testOnBorrow开启时,每次都进行检测连接可用性
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
} Connection realConnection = poolableConnection.conn; //获取真正驱动的连接对象
discardConnection(realConnection); //若连接不可用,则触发discard,这个方法具体放到流程1.4体现
continue;
}
} else {
Connection realConnection = poolableConnection.conn;
if (poolableConnection.conn.isClosed()) {
discardConnection(null); // 传入null,避免重复关闭
continue;
} if (testWhileIdle) { //不启用testOnBorrow的情况下,才会判断是否启用testWhileIdle
final DruidConnectionHolder holder = poolableConnection.holder;
long currentTimeMillis = System.currentTimeMillis();
long lastActiveTimeMillis = holder.lastActiveTimeMillis; //上次被使用的时间
long lastKeepTimeMillis = holder.lastKeepTimeMillis; if (lastKeepTimeMillis > lastActiveTimeMillis) {
lastActiveTimeMillis = lastKeepTimeMillis;
} long idleMillis = currentTimeMillis - lastActiveTimeMillis; //计算出闲置时间 long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis; if (timeBetweenEvictionRunsMillis <= 0) {
timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
} if (idleMillis >= timeBetweenEvictionRunsMillis || idleMillis < 0) { //当闲置时间超出timeBetweenEvictionRunsMillis(默认60s)时,则触发检查逻辑
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
} discardConnection(realConnection); //连接不可用,同样触发discard
continue;
}
}
}
} if (removeAbandoned) { //若开启removeAbandoned,则把当前拿到的连接放到activeConnections里,方便后续检查(后面流程4.2体现)
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
poolableConnection.connectStackTrace = stackTrace;
poolableConnection.setConnectedTimeNano(); //设置连接获取时间为当前时间
poolableConnection.traceEnable = true; //这个设置为true,则在归还该连接时会在activeConnections里清除掉该连接对象 activeConnectionLock.lock();
try {
activeConnections.put(poolableConnection, PRESENT);
} finally {
activeConnectionLock.unlock();
}
} if (!this.defaultAutoCommit) { //默认是不开事务的,所以这里是true,不会触发下面的逻辑;这个不建议手动设置默认值,一般开启事务的工作自己做或者交给第三方框架(如spring)做比较好
poolableConnection.setAutoCommit(false);
} return poolableConnection; //最终返回可用连接
}
}

Druid-代码段-1-1的更多相关文章

  1. WPF自定义RoutedEvent事件代码段

    今天在写东西的时候,发现常用的代码段里没有RoutedEvent的,因此,写了一个代码段,方便以后使用,顺便记录一下,如何做代码段. 1.在项目中新建一个XML文件,将扩展名修改为snippet. 2 ...

  2. JavaScript代码段整理笔记系列(二)

    上篇介绍了15个常用代码段,本篇将把剩余的15个补齐,希望对大家有所帮助!!! 16.检测Shift.Alt.Ctrl键: event.shiftKey; //检测Shift event.altKey ...

  3. 我们为什么要看《超实用的Node.JS代码段》

    不知道自己Node.JS水平如何?看这张图 如果一半以上的你都不会,必须看这本书,一线工程师用代码和功能页面来告诉你每一个技巧点. 都会一点,但不知道如何检验自己,看看本书提供的面试题: 1.     ...

  4. 《超实用的JavaScript代码段》—— 读后总结

    这本书全是代码,从头到尾跟着坐下来确实收获很多.比那些古板的教科书式的理解更多,不过书中并不是每个例子都做了,有的作者封装的太多,觉得看了收获不多,就没细看——比如模块渐变.有空好好学学这段的代码. ...

  5. Visual Studio常用小技巧一:代码段+快捷键+插件=效率

    用了visual studio 5年多,也该给自己做下备忘录了.每次进新的组换新的电脑,安装自己熟悉的环境又得重新配置,不做些备忘老会忘记一些东西.工具用的好,效率自然翻倍. 1,代码段 在Visua ...

  6. 使用eclipse开发Morphline的Java代码段

    背景:morphline是一个轻量级的etl工具.除了提供标准化的方法之外,还可以定制化的开发java片段.定制化的java片段会在加载时被作为一个独立的类编译,对源数据作处理. morphline关 ...

  7. 前端福利!10个短小却超实用的JavaScript 代码段

    JavaScript正变得越来越流行,它已经成为前端开发的第一选择,并且利用基于JavaScript语言的NodeJS,我们也可以开发出高 性能的后端服务,甚至我还看到在硬件编程领域也出现了JavaS ...

  8. Visual C# 代码段

    代码段是现成的代码段,您可以快速将其插入到您的代码中. 例如,for 代码段创建一个空的 for 循环. 有些代码段为外侧代码段,这些代码段允许您先选择代码行,然后选择要并入选定代码行的代码段. 例如 ...

  9. 十五个常用的jquery代码段【转】

    好的文章顶一个 回到顶部按钮 通过使用 jQuery 中的 animate 和 scrollTop 方法,你无需插件便可创建一个简单地回到顶部动画: 1 // Back to top 2 $('a.t ...

  10. 十五个常用的jquery代码段

    十五个常用的jquery代码段 回到顶部按钮 通过使用 jQuery 中的 animate 和 scrollTop 方法,你无需插件便可创建一个简单地回到顶部动画: 1 // Back to top ...

随机推荐

  1. Java程序员月薪三万,需要技术达到什么水平?

    最近跟朋友在一起聚会的时候,提了一个问题,说 Java 程序员如何能月薪达到二万,技术水平需要达到什么程度?人回答说这只能是大企业或者互联网企业工程师才能拿到.也许是的,小公司或者非互联网企业拿二万的 ...

  2. Nexus-在项目中使用Maven私服,Deploy到私服、上传第三方jar包、在项目中使用私服jar包

    场景 Ubuntu Server 上使用Docker Compose 部署Nexus(图文教程): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/ ...

  3. TSC打印机防重码在线检测系统

    条码标签作为产品的一个身份标识,被应用得越来越普及,但随着使用量的增大,在打印条码流水号的过程中,偶尔会出现打印重复号码的标签出现,这样对产品生产及管理过程中会产生极大的混乱,会收到严重的客诉及返工, ...

  4. double小数位数的显示

    不显示小数点后的0,只显示2位小数 DecimalFormat df = new DecimalFormat(".##"); double num = 450.029000089; ...

  5. vim简单操作命令

    vim简单操作命令: 开启编辑:按“i”或者“Insert”键 退出编辑:“Esc”键 退出vim:“:q” 保存vim:“:w” 保存退出vim:“:wq” 不保存退出vim:“:q!” 查看当前系 ...

  6. sqlplus命令窗口执行sql脚本文件

    SQL>@file_name 例如 SQL>@monitor.sql      文件须得在当前窗口所在的目录下或者指定某个路径. SQL>@D:\monitor.sql 转载示例-- ...

  7. s3c2440裸机-异常中断(一. 异常、中断的原理与流程)

    1.异常中断概述 在arm架构的处理器中,cpu有7中工作模式,2中工作状态. 1.CPU模式(Mode): 7种Mode: 除了usr/sys,其他5种都是异常模式.我们知道中断属于异常的2中,中断 ...

  8. PC上装VM上装虚拟机

    1.虚拟机网卡选择桥接模式 2.查看本PC机的网络 3.到/etc/sysconfig/network-scripts,修改网卡,vi ifcfg-ens33 4.重新/etc/init.d/netw ...

  9. unittest---unittest跳过用例

    我们在做自动化测试的时候,可能会遇到一些用例中间不用回归,想要进行跳过.直接注释的话,代码量修改过大,显然这个方法不妥,哪还有什么方法?unittest这个自动化框架可以帮助我们完成这个操作 自动跳过 ...

  10. 2.28秒创建一个k8s集群(非理论篇,理论自行 -- )

    准备3台centos 7+ (建议7以上,不然要会很麻烦,要升级内核等等,扯淡的东西) 安装docker 和k8s集群(均以最新版为例)基于官网 设置静态ip(可选) 查看本机的网关ip cd /Li ...