一、数据库连接池初始化

(1)、 如果设置了maxWait或者构造函数参数传入的为true,则创建的ReentrantLock为公平锁,否者为非公平锁
(2)、 如果设置了initialSize>=1,则会启动是创建initialSize个数数据库物理连接到线程池。
(3)、 如果没设置createScheduler则创建并启动数据库连接创建线程,如果没设置destroyScheduler则创建并启动数据库连接回收线程,如果timeBetweenLogStatsMillis>0则创建logstat线程。
二、获取数据库连接

(1)、 如果当前数据库连接池有可用连接,则直接获取,否者如果设置createScheduler则开启一个新线程去创建物理连接,否者发送发送signal信号唤醒连接创建线程创建数据库物理连接,这种情况有分pollLast和takeLast,区别在于前者设置max
wait超时时间,如果在时间内还没获取链接则返回null,后者则一直等待连接创建。
三、回收数据库连接

(1)、 在调用conn.close时候会回收当前连接到线程池
四、创建数据库连接线程

(1)、此图createScheduler=null的情况,为null从上面知道在初始化时候会新建
一个数据库连接创建线程。
五、连接池同步策略
实际上是个生产者消费者模式,生产者是连接创建线程和连接回收线程,消费者是获取连接的线程。
首先列下同步需要的条件变量和锁:
//独占锁(用来控制同是只有一个线程访问线程池),根据lockFair分为公平和非公平锁 lock = new ReentrantLock(lockFair); //用来对消费和生成线程做同步 notEmpty = lock.newCondition(); empty = lock.newCondition(); //共享资源,线程池是一个数组 connections = new DruidConnectionHolder[maxActive];
消费者(获取数据库连接线程):
DruidConnectionHolder pollLast(){ DruidConnectionHolder holder; try { //加独占锁 lock.lockInterruptibly(); } catch (InterruptedException e) { connectErrorCount.incrementAndGet(); throw new SQLException("interrupt", e); } try { //通知连接创建线程,创建数据库连接 empty.signal(); //等待连接创建线程或者连接回收线程发送信号 estimate = notEmpty.awaitNanos(estimate); //获取链接,并返回 decrementPoolingCount(); holder = connections[poolingCount]; connections[poolingCount] = null; }finally{ //释放独占锁 lock.unlock(); } holder.incrementUseCount(); DruidPooledConnection poolalbeConnection = new DruidPooledConnection(holder); return poolalbeConnection; }
生产者(连接创建线程):
public void run(){ try { //独占锁 lock.lockInterruptibly(); } catch (InterruptedException e2) { break; } try { // 必须存在线程等待,才创建连接 if (poolingCount >= notEmptyWaitThreadCount) { empty.await();//会释放当前独占锁 } // 防止创建超过maxActive数量的连接 if (activeCount + poolingCount >= maxActive) { empty.await();//会释放当前独占锁 } } finally { lock.unlock(); } Connection connection = null; try { //创建物理链接 connection = createPhysicalConnection(); } catch (SQLException e) { 。。。。 } catch (RuntimeException e) { 。。。。 } catch (Error e) { 。。。。 } lock.lock(); try { //连接入池 connections[poolingCount] = holder; incrementPoolingCount(); if (poolingCount > poolingPeak) { poolingPeak = poolingCount; poolingPeakTime = System.currentTimeMillis(); } //发出信号,激活消费线程 notEmpty.signal(); notEmptySignalCount++; } finally { lock.unlock(); } }
生产者(数据库连接回收线程):
protected void recycle(DruidPooledConnection pooledConnection){ lock.lockInterruptibly(); try { activeCount--; closeCount++; connections[poolingCount] = e; incrementPoolingCount(); if (poolingCount > poolingPeak) { poolingPeak = poolingCount; poolingPeakTime = lastActiveTimeMillis; } //激活消费线程 notEmpty.signal(); notEmptySignalCount++; recycleCount++; } finally { lock.unlock(); } }
文章转载自技术原始积累,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




