Druid05-连接关闭

1、连接关闭

​ 连接对象通过DruidPooledConnection 进行了包装,获取连接后都会进行连接的关闭或回收,如使用了类似 Mybatis、JPA 等开源框架通常会调用close方法,连接对象 DruidPooledConnection 重写了close()方法。

public void close() throws SQLException {
    //已关闭状态
    if (this.disable) {
        return;
    }
    DruidConnectionHolder holder = this.holder;
    if (holder == null) {
        if (dupCloseLogEnable) {
            LOG.error("dup close");
        }
        return;
    }
    DruidAbstractDataSource dataSource = holder.getDataSource();
    //关闭连接的线程和获取连接的线程是否是同一个
    boolean isSameThread = this.getOwnerThread() == Thread.currentThread();
    if (!isSameThread) {
        dataSource.setAsyncCloseConnectionEnable(true);
    }	
	//不是同一个线程则执行syncClose进行关闭
    if (dataSource.isAsyncCloseConnectionEnable()) {
        //避免并发关闭需要先获得锁
        syncClose();
        return;
    }
    //通过AtomicIntegerFieldUpdater保证只有一个线程在执行关闭
    if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) {
        return;
    }
    try {
        for (ConnectionEventListener listener : holder.getConnectionEventListeners()) {
            listener.connectionClosed(new ConnectionEvent(this));
        }
        //配置Filter,责任链执行后调用recycle方法
        List<Filter> filters = dataSource.getProxyFilters();
        if (filters.size() > 0) {
            //执行责任链
            FilterChainImpl filterChain = new FilterChainImpl(dataSource);
            filterChain.dataSource_recycle(this);
        } else {
            recycle();
        }
    } finally {
        CLOSING_UPDATER.set(this, 0);
    }
    this.disable = true;
}

  public void syncClose() throws SQLException {
    //需要先获得锁,再执行关闭
	lock.lock();
      try {
          //已关闭||其他线程在执行关闭
          if (this.disable || CLOSING_UPDATER.get(this) != 0) {
              return;
          }
          //和close基本一致
          ... 
          this.disable = true;
      } finally {
          CLOSING_UPDATER.set(this, 0);
          lock.unlock();
      }
}
2、recycle

通过DruidAbstractDataSource.recycle 方法判断数据库连接进行的关闭还是归还到线程池内,以及是否需要创建新的连接。

protected void recycle(DruidPooledConnection pooledConnection) throws SQLException {
    final DruidConnectionHolder holder = pooledConnection.holder;
    //日志打印
    if (holder == null) {
        LOG.warn("connectionHolder is null");
        return;
    }
    if (logDifferentThread
        && (!isAsyncCloseConnectionEnable()) 
        && pooledConnection.ownerThread != Thread.currentThread()) {
        LOG.warn("get/close not same thread");
    }
    final Connection physicalConnection = holder.conn;
    if (pooledConnection.traceEnable) {
        Object oldInfo = null;
        activeConnectionLock.lock();
        try {
            if (pooledConnection.traceEnable) {
                oldInfo = activeConnections.remove(pooledConnection);
                pooledConnection.traceEnable = false;
            }
        } finally {
            activeConnectionLock.unlock();
        }
        if (oldInfo == null) {
            if (LOG.isWarnEnabled()) {
                LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size());
            }
        }
    }

    final boolean isAutoCommit = holder.underlyingAutoCommit;
    final boolean isReadOnly = holder.underlyingReadOnly;
    final boolean testOnReturn = this.testOnReturn;

    try {
        // 判断非自动提交的事务是否存在事务
        if ((!isAutoCommit) && (!isReadOnly)) {
            //执行回滚
            pooledConnection.rollback();
        }
		//关闭连接的线程和获取连接的线程是否是同一个
        boolean isSameThread = pooledConnection.ownerThread == Thread.currentThread();
        if (!isSameThread) {
            final ReentrantLock lock = pooledConnection.lock;
            lock.lock();
            try {
                //将连接信息重置
                holder.reset();
            } finally {
                lock.unlock();
            }
        } else {
             //将连接信息重置
            holder.reset();
        }

        if (holder.discard) {
            return;
        }
        //是否超过最大物理连接数
        if (phyMaxUseCount > 0 && holder.useCount >= phyMaxUseCount) {
            //执行连接回收
            discardConnection(holder);
            return;
        }
		//判断连接是否已关闭
        if (physicalConnection.isClosed()) {
            lock.lock();
            try {
                if (holder.active) {
                    //活动线程数减1
                    activeCount--;
                    holder.active = false;
                }
               //关闭线程数加1
                closeCount++;
            } finally {
                lock.unlock();
            }
            return;
        }
		//是否开启回收连接时候判断连接是否可用
        if (testOnReturn) {
            boolean validate = testConnectionInternal(holder, physicalConnection);
              //连接不可用,调用close方法进行关闭
            if (!validate) {
                JdbcUtils.close(physicalConnection);
                destroyCountUpdater.incrementAndGet(this);
                lock.lock();
                try {
                    if (holder.active) {
                        activeCount--;
                        //活动线程数减1
                        holder.active = false;
                    }
                     //关闭线程数加1
                    closeCount++;
                } finally {
                    lock.unlock();
                }
                return;
            }
        }
        if (holder.initSchema != null) {
            holder.conn.setSchema(holder.initSchema);
            holder.initSchema = null;
        }
        if (!enable) {
            discardConnection(holder);
            return;
        }

        boolean result;
        final long currentTimeMillis = System.currentTimeMillis();
        //是否超过最大物理连接时间
        if (phyTimeoutMillis > 0) {
            long phyConnectTimeMillis = currentTimeMillis - holder.connectTimeMillis;
            if (phyConnectTimeMillis > phyTimeoutMillis) {
                //执行连接回收 activeCount <= minIdle 执行连接的创建
                discardConnection(holder);
                return;
            }
        }

        lock.lock();
        try {
            if (holder.active) {
                activeCount--;
                holder.active = false;
            }
            closeCount++;
            //将连接PUT到连接池
            result = putLast(holder, currentTimeMillis);
            recycleCount++;
        } finally {
            lock.unlock();
        }
        //添加到连接池失败,执行连接关闭
        if (!result) {
            JdbcUtils.close(holder.conn);
            LOG.info("connection recyle failed.");
        }
    } catch (Throwable e) {
        holder.clearStatementCache();
        if (!holder.discard) {
            discardConnection(holder);
            holder.discard = true;
        }
        LOG.error("recyle error", e);
        recycleErrorCountUpdater.incrementAndGet(this);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值