您的位置:首页 > 编程语言 > Java开发

Java——基于等待通知超时模式的连接池

2018-01-18 21:14 453 查看
连接池对象:
/**
* \* Created: liuhuichao
* \* Date: 2018/1/15
* \* Time: 下午1:35
* \* Description:连接池类-负责创建,持有连接
* \
*/
public class ConnectionPool {

private LinkedList<Connection> pool=new LinkedList<>();//从链表首部获取连接,从尾部回收连接

/**
* 数据库连接池构造函数
* @param initSize 连接池初始化大小
*/
public ConnectionPool(int initSize){
if(initSize>0){
for(int i=0;i<initSize;i++){
pool.addLast(ConnectionDriver.createConnection());
}
}
}

/**
* 获取连接
* @param mils 等待时间,即等待多久获取不到连接就超时
* @return
* @throws InterruptedException
*/
public Connection fetchConnection(long mils) throws InterruptedException{
synchronized (pool){
//当传入的参数为负数时候,不使用等待超时,直接是一直等待到获取到通知为止
if(mils<=0){
while (pool.isEmpty()){
pool.wait();
}
return pool.removeFirst();
}else{//超时等待。。。
long future=System.currentTimeMillis()+mils;
long remaining=mils;
while (pool.isEmpty()&&remaining>0){//使用等待超时模型
pool.wait(remaining);
remaining=future-System.currentTimeMillis();
}
/**注意,超时之后,说明一直没有获取到通知,此时,返回的连接为null**/
Connection result=null;
if(!pool.isEmpty()){
result=pool.removeFirst();
}
return result;
}
}
}

/**
* 释放连接
* @param connection
*/
public void releaseConnection(Connection connection){
if(connection!=null){
synchronized (pool){
//连接释放后需要进行通知,这样其他消费者能够感知到连接池中已经归还了一个连接
pool.addLast(connection);
pool.notifyAll();//通知所有等待的线程,可以获取连接了
}
}

}

}
获取连接:
/**
* \* Created: liuhuichao
* \* Date: 2018/1/15
* \* Time: 下午1:52
* \* Description:获取连接
* \
*/
public class ConnectionDriver {

/**
* 定义动态代理类
*/
static class ConnectionHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("commit")){
TimeUnit.MICROSECONDS.sleep(100);
}
return null;
}
}

/**
* 创建连接
* @return
*/
public static final Connection createConnection(){
return (Connection)Proxy.newProxyInstance(
ConnectionDriver.class.getClassLoader(),
new Class[]{Connection.class},
new ConnectionHandler());
}

}
测试连接:
/**
* \* Created: liuhuichao
* \* Date: 2018/1/17
* \* Time: 上午10:27
* \* Description:简单测试连接池
* \
*/
public class SimpleConnectionClientTest {

static ConnectionPool connectionPool=new ConnectionPool(10);

static AtomicInteger got=new AtomicInteger();

static AtomicInteger notGot=new AtomicInteger();

static int clientNum=100;//模拟客户端数量

static int waitConnectTimeout=100;//获取连接时候等待超时的时间

static int useConnectionTimeInterval=30;//客户端使用连接的时间

static CountDownLatch begin=new CountDownLatch(1);//用于控制线程同时开始的

static CountDownLatch finish=new CountDownLatch(clientNum);//用于保证main线程在所有客户端线程执行完之后可以获取执行结果

/**
* 测试代码
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {

for (int i=0;i<clientNum;i++){
Thread client=new Thread(new GetConnectionTest(),"client-"+(i+1));
client.start();
}

begin.countDown();//客户端线程初始化完毕,可以开始了

finish.await();
System.out.println("got="+got);
System.out.println("notGot="+notGot);
}

/**
* 用于模拟客户端获取连接
*/
static class GetConnectionTest implements Runnable{

@Override
public void run() {
try {
begin.await();
Connection conn=connectionPool.fetchConnection(waitConnectTimeout);
if(conn==null){
notGot.incrementAndGet();
}else{
got.incrementAndGet();
Thread.sleep(useConnectionTimeInterval);//表示使用连接的过程
connectionPool.releaseConnection(conn);//表示使用连接完成之后释放连接的过程
}
finish.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}

}
源码地址:https://github.com/SoledadVac/DataSourceConnectionPool
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: