//init方法是线程池创建方法

public void init() throws SQLException {

...

this.createAndLogThread();

this.createAndStartCreatorThread();

//调用创建销毁线程方法

this.createAndStartDestroyThread();

this.initedLatch.await();

...

}

//创建销毁线程

protected void createAndStartDestroyThread() {

this.destroyTask = new DruidDataSource.DestroyTask();

if(this.destroyScheduler != null) {

long period = this.timeBetweenEvictionRunsMillis;

if(period <= 0L) {

period = 1000L;

}

//启动销毁线程

this.destroySchedulerFuture = this.destroyScheduler.scheduleAtFixedRate(this.destroyTask, period, period, TimeUnit.MILLISECONDS);

this.initedLatch.countDown();

} else {

String threadName = "Druid-ConnectionPool-Destroy-" + System.identityHashCode(this);

this.destroyConnectionThread = new DruidDataSource.DestroyConnectionThread(threadName);

this.destroyConnectionThread.start();

}

}

//销毁线程

public class DestroyTask implements Runnable {

public DestroyTask() {

}

public void run() {

//checkTime 为true

DruidDataSource.this.shrink(true, DruidDataSource.this.keepAlive);

if(DruidDataSource.this.isRemoveAbandoned()) {

DruidDataSource.this.removeAbandoned();

}

}

}

//具体方法

public void shrink(boolean checkTime, boolean keepAlive) {

try {

this.lock.lockInterruptibly();

} catch (InterruptedException var49) {

return;

}

boolean needFill = false;

int evictCount = 0;

int keepAliveCount = 0;

int fatalErrorIncrement = this.fatalErrorCount - this.fatalErrorCountLastShrink;

this.fatalErrorCountLastShrink = this.fatalErrorCount;

int checkCount;

label956: {

try {

if(this.inited) {

//可能被销毁数量 = 线程池当前线程数量 - 配置的最小空闲数

checkCount = this.poolingCount - this.minIdle;

long currentTimeMillis = System.currentTimeMillis();

int i;

for(i = 0; i < this.poolingCount; ++i) {

DruidConnectionHolder connection = this.connections[i];

if((this.onFatalError || fatalErrorIncrement > 0) && this.lastFatalErrorTimeMillis > connection.connectTimeMillis) {

this.keepAliveConnections[keepAliveCount++] = connection;

} else if(checkTime) {

long idleMillis;

if(this.phyTimeoutMillis > 0L) {

idleMillis = currentTimeMillis - connection.connectTimeMillis;

if(idleMillis > this.phyTimeoutMillis) {

this.evictConnections[evictCount++] = connection;

continue;

}

}

//当前for循环处理的线程空闲时间 = 当前时间 - 连接最后活跃时间

idleMillis = currentTimeMillis - connection.lastActiveTimeMillis;

if(idleMillis < this.minEvictableIdleTimeMillis && idleMillis < this.keepAliveBetweenTimeMillis) {

break;

}

//连接空闲时间 >= 配置的最小空闲被回收时间 : minEvictableIdleTimeMillis

if(idleMillis >= this.minEvictableIdleTimeMillis) {

/*

checkTime 为方法入参 = true,

i:当前for循环下标(连接取得时候是取得数组最大坐标,新创建的连接也是放在数组最大坐标上,所以0号坐标一定是最久未使用的那个)

可能被销毁数量 = 线程池当前线程数量 - 配置的最小空闲数(checkCount = this.poolingCount - this.minIdle; )

重点 : 也就是minEvictableIdleTimeMillis配置只会回收超过minIdle的那部分空闲连接

*/

if(checkTime && i < checkCount) {

this.evictConnections[evictCount++] = connection;

continue;

}

//连接空闲时间 > 配置的最大空闲时间maxEvictableIdleTimeMillis

//重点 : maxEvictableIdleTimeMillis参数会忽略配置的minIdle

if(idleMillis > this.maxEvictableIdleTimeMillis) {

this.evictConnections[evictCount++] = connection;

continue;

}

}

if(keepAlive && idleMillis >= this.keepAliveBetweenTimeMillis) {

this.keepAliveConnections[keepAliveCount++] = connection;

}

} else {

if(i >= checkCount) {

break;

}

this.evictConnections[evictCount++] = connection;

}

}

i = evictCount + keepAliveCount;

if(i > 0) { //复制有效连接到连接池数组

System.arraycopy(this.connections, i, this.connections, 0, this.poolingCount - i);

Arrays.fill(this.connections, this.poolingCount - i, this.poolingCount, (Object)null);

this.poolingCount -= i;

}

this.keepAliveCheckCount += keepAliveCount;

if(keepAlive && this.poolingCount + this.activeCount < this.minIdle) {

needFill = true;

}

break label956;

}

} finally {

this.lock.unlock();

}

return;

}

Connection connection;

DruidConnectionHolder holer;

if(evictCount > 0) { //销毁刚刚放在数组里的连接

for(checkCount = 0; checkCount < evictCount; ++checkCount) {

holer = this.evictConnections[checkCount];

connection = holer.getConnection();

JdbcUtils.close(connection);

destroyCountUpdater.incrementAndGet(this);

}

Arrays.fill(this.evictConnections, (Object)null);

}

...

}

修改mysql连接回收时间_Druid无效链接回收策略(源码分析)(mysql 8小时连接失效问题)...相关推荐

  1. AsyncHttpClient源码分析-基于Netty的连接池实现

    原文地址:asynchttpclient源码分析-基于Netty的连接池实现 最近项目重构,有了个机会更多接触一个有别于HttpAsyncClient的异步网络框架AsyncHttpClient,是个 ...

  2. 云客Drupal源码分析之菜单上下文连接Menu contextual links

    drupal可以为页面中的局部区域提供额外的链接,通常用这些链接指向和这个区域相关的页面,这些链接就是本篇所说的菜单上下文链接,在drupal中被大量运用,她们位于哪里呢?以默认安装为例:以管理员身份 ...

  3. linux网络协议栈源码分析 - 传输层(TCP连接的建立)

    1.bind系统调用 1.1.地址端口及状态检查(inet_bind) 通过路由表查找绑定地址的路由类型,对于非本地IP检查是否允许绑定非本地IP地址:检查公认端口绑定权限,是否允许绑定0~1024端 ...

  4. mysql源码分析书籍_从源码分析 MySQL 死锁问题入门

    链接:https://juejin.im/post/5ce287326fb9a07ea8039d70 这篇文章主要讲的是如何通过调试 MySQL 源码,知道一条 SQL 真正会拿哪些锁,不再抓虾,瞎猜 ...

  5. 从源码分析 MySQL Group Replication 的流控机制

    Group Replication 是一种 Shared-Nothing 的架构,每个节点都会保留一份数据. 虽然支持多点写入,但实际上系统的吞吐量是由处理能力最弱的那个节点决定的. 如果各个节点的处 ...

  6. MySQL · 源码分析 · MySQL 半同步复制数据一致性分析

    简介 MySQL Replication为MySQL用户提供了高可用性和可扩展性解决方案.本文介绍了MySQL Replication的主要发展历程,然后通过三个参数rpl_semi_sync_mas ...

  7. 悟空分词与mysql结合_悟空分词的搜索和排序源码分析之——搜索

    转自:http://blog.codeg.cn/2016/02/02/wukong-source-code-reading/ 搜索过程分析 下面我们来分析一下搜索的过程.首先构造一个SearchReq ...

  8. 悟空分词与mysql结合_悟空分词的搜索和排序源码分析之——索引

    转自:http://blog.codeg.cn/2016/02/02/wukong-source-code-reading/ 索引过程分析 下面我们来分析索引过程. // 将文档加入索引 // // ...

  9. linux怎么用源码安装mysql,Linux源码安装mysql步骤

    创建文件夹: mkdir  /usr/local/webserver 安装必要依赖包 yum -y install gcc gcc-c++ make ncurses-devel 安装cmake包: t ...

  10. 【Netty源码分析摘录】(八)新连接的接入

    文章目录 1.问题 2.检测新连接接入 3.创建客户端 channel 4. 绑定 NioEventLoop 4.1 register0 4.1.1 doRegister() 4.1.2 pipeli ...

最新文章

  1. 网曝抖音电商变相降薪!总包不变,base降低,分摊到年终奖!
  2. python版mapreduce题目实现寻找共同好友
  3. java做台球时老是闪屏_电脑老是闪屏的原因和解决办法
  4. 【BZOJ4559】【JLOI2016】—成绩比较(拉格朗日插值+dp)
  5. 重磅!13所985高校,成立大学联盟!
  6. 加分二叉树(洛谷-P1040)
  7. linux挂接u盘视频,LINUX挂接U盘
  8. 服务器上出现应用程序错误。此应用程序的当前自定义错误设置禁止远程查看应用程序错误的详细信息(出于安全原因)。...
  9. Eclipse : Android requires compiler compliance level 5.0 or 6.0.
  10. 7.TCP/IP 详解卷1 --- Ping 程序
  11. db9口rs485引脚接收和发送定义
  12. GB28181标准文档以及GB35114标准文档免费下载
  13. Linux下笔记本电源管理
  14. 今日头条号如何过原创
  15. CyberArk被评为2022年Gartner特权访问管理魔力象限领导者
  16. 婚介行业线上引流渠道哪些?你还在为找不到客户而烦恼吗?这些渠道千万别错过!
  17. 广州大学学生实验报告,数据结构实验,二叉树的操作与实现
  18. AMCL代码详解(七)amcl中的kd-Tree
  19. mysql命令行界面出现问题,MySQL命令行界面中出现字符错误提示的原因及解决方法...
  20. 有关channel的相关知识(2)

热门文章

  1. 1到20的阶乘倒数之和
  2. NYOJ 214(二分插入)
  3. scipy.optimize.curve_fit
  4. ENVI扩展工具——混合像元分解FCLS
  5. ArcGIS 制作林地成分栅格数据
  6. 基于遥感影像实现三种方法提取枣树面积精度分析
  7. 【移动GIS】室内导航算法设计
  8. Java中数字朝着0.5的倍数取舍
  9. vue混入html,vue混入(mixins)的应用
  10. 打造AS酷炫dimens适配插件