1.下面我们就使用等待超时模式构造简单数据库连接池,模拟从连接池中获取,使用和释放连接的过程,而客户端获取连接的过程被设定为等待超时模式,在1000 ms内无法获取到可用连接将会返回给客户端一个null,设定连接池大小为10,然后通过调节客户端线程数来模拟无法获取连接的场景。
2.连接池的定义:
通过构造函数初始化最大的连接上限,通过双向队列来维护连接,调用方先调用fetchConnection(long)方法来指定多少毫秒内超时获取连接,当连接使用完成后调用releaseConnectiion(Connection)方法将连接放回线程池。
3.代码
ConnectionPool.java
package connectionpool;
import java.util.*;
import java.sql.*;
public class ConnectionPool {
private LinkedList<Connection> pool=new LinkedList<Connection>();
public ConnectionPool(int initialSize)
{//构造initialSize个线程的线程池
if(initialSize>0)
{
for(int i=0;i<initialSize;i++)
{
pool.addLast(ConnectionDriver.createConnection());
}
}
}
public void releaseConnection(Connection connection)
{//连接释放后使用notifyAll通知其他线程并将释放的连接放回到连接池
if(connection!=null)
{
synchronized(pool)
{
pool.addLast(connection);
pool.notifyAll();
}
}
}
public Connection fetchConnection(long mills) throws InterruptedException
{//在mills毫秒内无法获取连接就返回null
synchronized(pool)
{
if(mills<=0)
{//完全超时
while(pool.isEmpty())
{//连接池为空,等待
pool.wait();
}
return pool.removeFirst();//返回获取的连接
}
else
{
long future=System.currentTimeMillis()+mills;
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;
}
}
}
}
package connectionpool;
import java.lang.reflect.*;
import java.util.concurrent.TimeUnit;
import java.sql.*;
public class ConnectionDriver
{
static class ConnectionHandler implements InvocationHandler
{
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
{
if(method.getName().equals("commit"))
{
TimeUnit.MILLISECONDS.sleep(100);
}
return null;
}
}
public static final Connection createConnection()
{
return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(),new Class<?>[]{Connection.class},new ConnectionHandler());
}
}
package connectionpool;
import java.util.*;
import java.sql.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ConnectionPoolTest {
static ConnectionPool pool=new ConnectionPool(10);//创建连接池
static CountDownLatch start=new CountDownLatch(1);
static CountDownLatch end;
public static void main(String []args) throws Exception
{
int threadCount=10;
end=new CountDownLatch(threadCount);
int count=20;
AtomicInteger got=new AtomicInteger();
AtomicInteger notgot=new AtomicInteger();
for(int i=0;i<threadCount;i++)
{
Thread thread=new Thread(new ConnectionRunner(count,got,notgot),"ConnectionRunnerThread");
thread.start();
}
start.countDown();
end.await();//当计数器减为0就不再阻塞
System.out.println("total invoke:"+(threadCount*count));
System.out.println("got connection:"+got);
System.out.println("not got connection "+notgot);
}
static class ConnectionRunner implements Runnable
{
int count;
AtomicInteger got;//连接获取的数量
AtomicInteger notgot;//连接未获取的数量
public ConnectionRunner(int count,AtomicInteger got,AtomicInteger notgot)
{
this.count=count;
this.got=got;
this.notgot=notgot;
}
@Override
public void run()
{
try
{
start.await();
}
catch(Exception ex)
{
}
while(count>0)
{
try
{
Connection connection=pool.fetchConnection(1000);//从连接池获取连接并设置超时时间间隔
if(connection!=null)
{
try
{
//操作数据库并提交操作
connection.createStatement();
connection.commit();
}finally{
//操作完后释放连接并放回连接池
pool.releaseConnection(connection);
got.incrementAndGet();//获取到连接的数量加1
}
}
else
{//未成功获取到连接则notgot加1
notgot.incrementAndGet();
}
}catch(Exception ex){}
finally{
count--;
}
}
end.countDown();
}
}
}