java数据库连接池_方便自己学习

1、利用的等待 / 通知实现超时取连接

package cn.enjoyedu.ch1.pool;

import java.sql.Connection;
import java.util.LinkedList;

/**
类说明:连接池的实现
/
public class DBPool {

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">容器用于存放连接</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> LinkedList&lt;Connection&gt; pool = <span style="color: rgba(0, 0, 255, 1)">new</span> LinkedList&lt;Connection&gt;<span style="color: rgba(0, 0, 0, 1)">();

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">限制了连接池的大小</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> DBPool(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> initialSize) {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (initialSize &gt; 0<span style="color: rgba(0, 0, 0, 1)">) {
        </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; initialSize; i++<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">模拟拿连接</span>

pool.addLast(SqlConnectImpl.fetchConnection());
}
}
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">释放连接,通知其他的等待连接的线程</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> releaseConnection(Connection connection) {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (connection != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
        </span><span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> (pool){
            pool.addLast(connection);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通知其他等待连接的线程</span>

pool.notifyAll();
}
}
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">获取</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在mills内无法获取到连接,将会返回null 1S</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> Connection fetchConnection(<span style="color: rgba(0, 0, 255, 1)">long</span> mills) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> InterruptedException {
    </span><span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> (pool){
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">永不超时</span>
        <span style="color: rgba(0, 0, 255, 1)">if</span>(mills&lt;=0<span style="color: rgba(0, 0, 0, 1)">){
            </span><span style="color: rgba(0, 0, 255, 1)">while</span><span style="color: rgba(0, 0, 0, 1)">(pool.isEmpty()){
                pool.wait();
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> pool.removeFirst();
        }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
            </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">超时时刻</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
            <span style="color: rgba(0, 0, 255, 1)">long</span> future = System.currentTimeMillis()+<span style="color: rgba(0, 0, 0, 1)">mills;
            </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">等待时长</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
            <span style="color: rgba(0, 0, 255, 1)">long</span> remaining =<span style="color: rgba(0, 0, 0, 1)"> mills;
            </span><span style="color: rgba(0, 0, 255, 1)">while</span>(pool.isEmpty()&amp;&amp;remaining&gt;0<span style="color: rgba(0, 0, 0, 1)">){
                pool.wait(remaining);
                </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">唤醒一次,重新计算等待时长</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
                remaining </span>= future-<span style="color: rgba(0, 0, 0, 1)">System.currentTimeMillis();
            }
            Connection connection </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">pool.isEmpty()){
                connection </span>=<span style="color: rgba(0, 0, 0, 1)"> pool.removeFirst();
            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> connection;
        }
    }

}

}

测试

package com.pool;

import java.sql.Connection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
类说明:测试并发 1000 次从池拿连接
/
public class DBPoolTest {
static DBPool pool = new DBPool(10);
// 控制器: 控制 main 线程将会等待所有 Woker 结束后才能继续执行
static CountDownLatch end;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> main(String[] args) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 线程数量</span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> threadCount = 50<span style="color: rgba(0, 0, 0, 1)">;
    end </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> CountDownLatch(threadCount);
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> count = 20;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">每个线程的操作次数</span>
    AtomicInteger got = <span style="color: rgba(0, 0, 255, 1)">new</span> AtomicInteger();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">计数器:统计可以拿到连接的线程</span>
    AtomicInteger notGot = <span style="color: rgba(0, 0, 255, 1)">new</span> AtomicInteger();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">计数器:统计没有拿到连接的线程</span>
    <span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; threadCount; i++<span style="color: rgba(0, 0, 0, 1)">) {
        Thread thread </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Thread(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Worker(count, got, notGot), 
                </span>"worker_"+<span style="color: rgba(0, 0, 0, 1)">i);
        thread.start();
    }
    end.await();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> main线程在此处等待</span>
    System.out.println("总共尝试了: " + (threadCount *<span style="color: rgba(0, 0, 0, 1)"> count));
    System.out.println(</span>"拿到连接的次数:  " +<span style="color: rgba(0, 0, 0, 1)"> got);
    System.out.println(</span>"没能连接的次数: " +<span style="color: rgba(0, 0, 0, 1)"> notGot);
}

</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span> Worker <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> Runnable {
    </span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">           count;
    AtomicInteger got;
    AtomicInteger notGot;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> Worker(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> count, AtomicInteger got,
                           AtomicInteger notGot) {
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.count =<span style="color: rgba(0, 0, 0, 1)"> count;
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.got =<span style="color: rgba(0, 0, 0, 1)"> got;
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.notGot =<span style="color: rgba(0, 0, 0, 1)"> notGot;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> run() {
        </span><span style="color: rgba(0, 0, 255, 1)">while</span> (count &gt; 0<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 从线程池中获取连接,如果1000ms内无法获取到,将会返回null
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 分别统计连接获取的数量got和未获取到的数量notGot</span>
                Connection connection = pool.fetchConnection(1000<span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (connection != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                        connection.createStatement();</span>

connection.commit();
}
finally {
pool.releaseConnection(connection);
got.incrementAndGet();
}
}
else {
notGot.incrementAndGet();
System.out.println(Thread.currentThread().getName()
+"等待超时!");
}
}
catch (Exception ex) {
}
finally {
count
--;
}
}
end.countDown();
}
}
}

结果

2、利用信号量实现数据库连接池:

注意可用连接 useful无可用连接 useless都要管理起来,因为你不能保证每个人都会先拿连接再释放连接,这是信号量的一个坑

package com.semaphore;

import java.sql.Connection;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;

/**
类说明:Semaphore 实现数据库连接池
/
public class DBPoolSemaphore {

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> POOL_SIZE = 10<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">两个指示器,分别表示池子还有可用连接和已用连接</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">final</span><span style="color: rgba(0, 0, 0, 1)"> Semaphore useful,useless;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">存放数据库连接的容器</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> LinkedList&lt;Connection&gt; pool = <span style="color: rgba(0, 0, 255, 1)">new</span> LinkedList&lt;Connection&gt;<span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">初始化池</span>
<span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; POOL_SIZE; i++<span style="color: rgba(0, 0, 0, 1)">) {
        pool.addLast(SqlConnectImpl.fetchConnection());
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> DBPoolSemaphore() {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.useful = <span style="color: rgba(0, 0, 255, 1)">new</span> Semaphore(10<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.useless = <span style="color: rgba(0, 0, 255, 1)">new</span> Semaphore(0<span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">归还连接</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> returnConnect(Connection connection) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> InterruptedException {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(connection!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
        System.out.println(</span>"当前有"+useful.getQueueLength()+"个线程等待数据库连接!!"
                +"可用连接数:"+<span style="color: rgba(0, 0, 0, 1)">useful.availablePermits());
        useless.acquire();
        </span><span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> (pool) {
            pool.addLast(connection);
        }
        useful.release();
    }
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">从池子拿连接</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> Connection takeConnect() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> InterruptedException {
    useful.acquire();
    Connection connection;
    </span><span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> (pool) {
        connection </span>=<span style="color: rgba(0, 0, 0, 1)"> pool.removeFirst();
    }
    useless.release();
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> connection;
}

}

测试

package com.semaphore;

import java.sql.Connection;
import java.util.Random;

/**
类说明:测试数据库连接池
/
public class AppTest {

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> DBPoolSemaphore dbPool = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> DBPoolSemaphore();

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span> BusiThread <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Thread{
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> run() {
        Random r </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Random();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">让每个线程持有连接的时间不一样</span>
        <span style="color: rgba(0, 0, 255, 1)">long</span> start =<span style="color: rgba(0, 0, 0, 1)"> System.currentTimeMillis();
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            Connection connect </span>=<span style="color: rgba(0, 0, 0, 1)"> dbPool.takeConnect();
            System.out.println(</span>"Thread_"+<span style="color: rgba(0, 0, 0, 1)">Thread.currentThread().getId()
                    </span>+"_获取数据库连接共耗时【"+(System.currentTimeMillis()-start)+"】ms."<span style="color: rgba(0, 0, 0, 1)">);
            SleepTools.ms(</span>100+r.nextInt(100));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">模拟业务操作,线程持有连接查询数据</span>
            System.out.println("查询数据完成,归还连接!"<span style="color: rgba(0, 0, 0, 1)">);
            dbPool.returnConnect(connect);
        } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InterruptedException e) {
        }
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
    </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; 50; i++<span style="color: rgba(0, 0, 0, 1)">) {
        Thread thread </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BusiThread();
        thread.start();
    }
}

}

结果

 Semaphore 信号量的一个坑,只管理可用连接,当开发者不按先取连接再释放连接的规则,就达不到流控的效果,

package com.semaphore;

import java.sql.Connection;
import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.Semaphore;

/**
类说明:Semaphore 实现数据库连接池
/
public class DBPoolNoUseless {

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> POOL_SIZE = 10<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">final</span><span style="color: rgba(0, 0, 0, 1)"> Semaphore useful;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">存放数据库连接的容器</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> LinkedList&lt;Connection&gt; pool = <span style="color: rgba(0, 0, 255, 1)">new</span> LinkedList&lt;Connection&gt;<span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">初始化池</span>
<span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; POOL_SIZE; i++<span style="color: rgba(0, 0, 0, 1)">) {
        pool.addLast(SqlConnectImpl.fetchConnection());
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> DBPoolNoUseless() {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.useful = <span style="color: rgba(0, 0, 255, 1)">new</span> Semaphore(10<span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">归还连接</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> returnConnect(Connection connection) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> InterruptedException {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(connection!=<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
        System.out.println(</span>"当前有"+useful.getQueueLength()+"个线程等待数据库连接!!"
                +"可用连接数:"+<span style="color: rgba(0, 0, 0, 1)">useful.availablePermits());
        </span><span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> (pool) {
            pool.addLast(connection);
        }
        useful.release();
    }
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">从池子拿连接</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> Connection takeConnect() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> InterruptedException {
    useful.acquire();
    Connection connection;
    </span><span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> (pool) {
        connection </span>=<span style="color: rgba(0, 0, 0, 1)"> pool.removeFirst();
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> connection;
}

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> DBPoolNoUseless dbPoolNoUseless = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> DBPoolNoUseless();

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span> BusiThread <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Thread{
    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> run() {
        Random r </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Random();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">让每个线程持有连接的时间不一样</span>
        <span style="color: rgba(0, 0, 255, 1)">long</span> start =<span style="color: rgba(0, 0, 0, 1)"> System.currentTimeMillis();
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            System.out.println(</span>"Thread_"+<span style="color: rgba(0, 0, 0, 1)">Thread.currentThread().getId()
                    </span>+"_获取数据库连接共耗时【"+(System.currentTimeMillis()-start)+"】ms."<span style="color: rgba(0, 0, 0, 1)">);
            SleepTools.ms(</span>100+r.nextInt(100));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">模拟业务操作,线程持有连接查询数据</span>
            System.out.println("查询数据完成,归还连接!"<span style="color: rgba(0, 0, 0, 1)">);
            dbPoolNoUseless.returnConnect(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SqlConnectImpl());
        } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InterruptedException e) {
        }
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
    </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; 50; i++<span style="color: rgba(0, 0, 0, 1)">) {
        Thread thread </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BusiThread();
        thread.start();
    }
}

}

 模拟拿连接的类:

package cn.enjoyedu.ch1.pool;

import cn.enjoyedu.tools.SleepTools;

import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
类说明:
/
public class SqlConnectImpl implements Connection{

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">拿一个数据库连接</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span><span style="color: rgba(0, 0, 0, 1)"> Connection fetchConnection(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SqlConnectImpl();
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">忽略其它    </span>

}