连接池的原理:为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。
连接池的定义:它通过构造函数初始化连接的最大上限,通过一个双向队列来维护连接,调用方需要先调用fetchConnection(long)方法来指定在多少毫秒内超时获取连接,当连接使用完成后,需要调用releaseConnection(Connection)方法将连接放回到连接池。
package default1;
import java.sql.Connection;
import java.util.LinkedList;
import javax.sql.PooledConnection;
public class ConnectionPool {
private LinkedList<Connection> pool=new LinkedList<Connection>();
//将创建的连接放在linkedlist中
public ConnectionPool(int initialSize){//创建连接池
for(int i=0;i<initialSize;i++){
pool.add(ConnectionDriver.createConnection());
}
}
public void realeaseConnection(Connection connection){
if(connection!=null){
synchronized (pool) {
//连接释放后需要进行通知,这样其他消费者能感知到连接池已经归还一个链接
pool.add(connection);
pool.notifyAll();
}
}
}
//在mills内无法获得连接则返回null
public Connection fetchConnection(long mills) throws InterruptedException{
synchronized (pool) {
if(mills<=0){//完全超时
while(pool.isEmpty()){
pool.wait(); //如果连接池为空,则
}
return pool.removeFirst();
}
else{
long future =mills+System.currentTimeMillis();
long remaining=mills;
while(pool.isEmpty()&&remaining>0){
pool.wait(remaining);
remaining=future-System.currentTimeMillis();
}
Connection result=null;
if(!pool.isEmpty()){
result=pool.removeFirst();
}
return result;}}}}
public class ConnectionPoolTest {
static ConnectionPool pool=new ConnectionPool(10);
//保证所有ConnectionRunner能够同时开始
static CountDownLatch start=new CountDownLatch(1);
//main线程将会等待所有ConnectionRunner结束后才能继续执行
static CountDownLatch end;
/*CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
主要方法
public CountDownLatch(int count);
public void countDown();
public void await() throws InterruptedException
构造方法参数指定了计数的次数
countDown方法,当前线程调用此方法,则计数减一
awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0*/
public static void main(String[] args)throws Exception {
//线程数量,可以修改线程数量进行观察
int threadCount=20;
end=new CountDownLatch(threadCount);
int count=20;
AtomicInteger got=new AtomicInteger();
AtomicInteger nogot=new AtomicInteger();
for(int i=0;i<threadCount;i++){
Thread thread=new Thread(new ConnectionRunner(count,got,nogot),"ConnectionRunnerThread");
thread.start();
}
start.countDown();
end.await();
System.out.println("total invoke: "+(threadCount*count));
System.out.println("got connection: "+got);
System.out.println("not got connection "+nogot);
}
static class ConnectionRunner implements Runnable{
int count;
AtomicInteger got;
AtomicInteger nogot;
public ConnectionRunner(int count, AtomicInteger got, AtomicInteger nogot) {
// TODO Auto-generated constructor stub
this.count=count;
this.got=got;
this.nogot=nogot;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
start.await();
}catch(Exception ex){
}
while(count>0){
try{
//从连接池中获取连接,如果1000ms内无法获取到,将会返回null
//分别从统计连接获取的数量got和未获取到的数量nogot
Connection connection=pool.fetchConnection(1000);
if(connection!=null){
try{
connection.createStatement();
connection.commit();
}finally{
pool.releaseConnection(connection);
got.incrementAndGet();
}
}else{
nogot.incrementAndGet();
}
}catch(Exception ex){
}finally {
count--;
}
}
end.countDown();
}
}
}