1.概述

频繁的创建和销毁数据库连接消耗非常多的系统资源,创建一个池子, 管理一定数量的连接,用的时候去池中取,用完了放回池中,这时比较通用的做法。

2.关键字

LinkedList  synchronized  InvocationHandler  CountDownLatch

3. 代码

3.1 ConnectionPool.java

package com.rocky.pool;

import java.sql.Connection;
import java.util.LinkedList; public class ConnectionPool { private LinkedList<Connection> pool = new LinkedList<Connection>(); public ConnectionPool(int initialSize){
if(initialSize > 0){
for(int i=0; i<initialSize; i++){
pool.addLast(ConnectionDriver.createConection());
}
}
} public void releaseConnection(Connection connection){
if(connection != null){
synchronized (pool) {
//连接释放后 要进行通知 这样其他消费者能够感知池中已经归还了一个连接
pool.addLast(connection);
// pool.notifyAll();//all
pool.notify();//all }
}
} public Connection fetchConnection(long mills) throws InterruptedException{
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;
}
} }
}

3.2 ConnectionDriver.java

package com.rocky.pool;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection; 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")){
Thread.sleep(1000);
}
return null;
}
} //创建一个connection的代理
public static Connection createConection(){
return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(), new Class<?>[]{Connection.class},new ConnectionHandler());
}
}

3.3 ConnectionPoolTest.java

package com.rocky.pool;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger; public class ConnectionPoolTest { static ConnectionPool pool = new ConnectionPool(10); //保证所有runner能够同时运行
static CountDownLatch start = new CountDownLatch(1); static CountDownLatch end ; public static void main(String[] args) throws Exception {
int threadCount = 20; 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), "ConectionRunnerThread"+i);
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 "+ 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 (InterruptedException e) {
e.printStackTrace();
}
while(count > 0){
try {
Connection connection = pool.fetchConnection(1000);
if(connection != null){
try{
connection.createStatement();
connection.commit();
}finally{
pool.releaseConnection(connection);
got.incrementAndGet();
}
}else{
notGot.incrementAndGet();
}
} catch (InterruptedException | SQLException e) {
e.printStackTrace();
}finally{
count--;
}
}
end.countDown();
} } }

3.4 说明

通过改变main方法中的threadCount的数量可以观察 随着线程数的增加 获取连接命中的比例在下降,

这时因为连接池中的连接数一定(10个) 而客户端线程会等待并超时返回。

简单的数据库连接池实例(java语言)的更多相关文章

  1. 数据源与JNDI资源实现JSP数据库连接池实例

    名词解释:JNDI的全称是java命名与目录接口(Java Naming and Directory Interface),是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通 ...

  2. [数据库连接池二]Java数据库连接池--C3P0和JDNI.

    前言:上一篇文章中讲了DBCP的用法以及实现原理, 这一篇再来说下C3P0和JDNI的用法. 1.1.C3P0数据源 C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规 ...

  3. mongodb数据库连接池(java版)

    mongodb数据库接口的设计 package storm.db; import java.util.ArrayList; import com.mongodb.DB; import com.mong ...

  4. 简单理解数据库连接池(JDBC)

    为什么要使用连接池? 在我们写代码的时候,写了很多类,假如这些类都和数据库打交道.这样的话每个类都要去获取数据库连接,操作完了之后就把连接释放了. 要知道,获取数据库连接的操作其实是向操作系统底层去获 ...

  5. Python数据库连接池实例——PooledDB

    不用连接池的MySQL连接方法 import MySQLdbconn= MySQLdb.connect(host='localhost',user='root',passwd='pwd',db='my ...

  6. Python数据库连接池实例——PooledDB

    不用连接池的MySQL连接方法 import MySQLdb conn= MySQLdb.connect(host='localhost',user='root',passwd='pwd',db='m ...

  7. dbcp数据库连接池的java实现

    1.准备 导入jar包 commons-dbcp-1.4.jar commons-pool-1.3.jar 数据库驱动包,如:mysql-connector-java-5.1.28-bin.jar 2 ...

  8. C3P0数据库连接池的java实现

    1.配置准备 导入jar包 c3p0-0.9.2-pre1.jar mchange-commons-0.2.jar 数据库驱动包,如:mysql-connector-java-5.1.28-bin.j ...

  9. 第77节:Java中的事务和数据库连接池和DBUtiles

    第77节:Java中的事务和数据库连接池和DBUtiles 前言 看哭你,字数:8803,承蒙关照,谢谢朋友点赞! 事务 Transaction事务,什么是事务,事务是包含一组操作,这组操作里面包含许 ...

随机推荐

  1. nginx高性能WEB服务器系列之三版本升级

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  2. Review notes

  3. Maven 远程仓库下载慢的的解决方案

    配置很简单,修改conf文件夹下的settings.xml文件,添加如下镜像配置: 我直接去设置maven目录下面的setttings文件 添加镜像站点 <mirrors> <mir ...

  4. 实验吧之deeeeeeaaaaaadbeeeeeeeeeef-200

    题目中提示说“图片是正确的吗”,赶紧打开图片,图片显示正常,没啥毛病,那就放到winhex里面,好像它的十六进制格式也蛮标准的,然后它的文本区域有个iphone,这个梗我也是百度才知道的: winhe ...

  5. docker 容器container运行后,如何进入容器内部?

    docker exec -ti  容器ID  /bin/bash

  6. JS之作用域与闭包

    JS之作用域与闭包   作用域在JS中同样也是一个重要的概念.它不复杂,因为ES5中只有全局作用域和函数作用域,我们都知道他没有块级作用域.但在ES6中多了一个let,他可以保证外层块不受内层块的影响 ...

  7. Zookeeper---系统学习

    1.概述 1.1 Zookeeper解决了什么问题? 分布式环境中    协调和管理服务    是一个复杂的过程: Zookeeper通过  其简单的架构和API  解决了这个问题,Zookeeper ...

  8. ionic3 cordova 调取软键盘

    应用场景,因为兼容ios,安卓问题,不能直接调用激活软键盘方法.只有在点击按钮时让input框自动获取焦点,激活软键盘.然后把input框定位在键盘上方,软键盘激活可以监听到键盘高度. 先下载keyb ...

  9. vue中$nextTick的用法

    简介 vue是非常流行的框架,他结合了angular和react的优点,从而形成了一个轻量级的易上手的具有双向数据绑定特性的mvvm框架.本人比较喜欢用之.在我们用vue时,我们经常用到一个方法是th ...

  10. Java学习之路(二):流程控制语句

    Java流程控制语句 java的流程控制语句: 默认,顺序执行 if...else...条件控制语句 switch 选择语句 for循环 while循环 do...while循环 break,cont ...