数据库连接池原理 与实现(动脑学院Jack老师课后自己的练习有感)
第一步: 首先创建一个数据库连接池的接口:
数据库连接池接口有两个主要的方法,其中一个getConnection(); 通过数据库连接池返回给用户封装的数据库连接对象
createConnections(int count);是当数据库连接池中的连接不够用的时候用来创建数据库连接个数;
参数解释: 首先,vector是我们所用的数据库连接池,其中用来存储我们所需要的数据库连接的个数,就相当于一个池子,当人们需要数据库连接时候只需要去vector中去拿就可以了,首先,因为有池子,池子中就一定要有初始化的数据库连接, 所以用一个init()函数,将池子中进行初始化,
初始化字段:
public static String jdbcDriver="";
public static String dbUserName="";
public static String dbPassword="";
public static String dbUrl="";
public static int initConCount;
public static int maxConnects;
public static int inCrementalcount;
这些字段的定义是从对应的properties文件中读取数据, 分别是数据库驱动,账号,密码,数据库地址,初始化的连接数目,连接池中的最大连接数,当达到了最大个数,增加连接池中的个数。这些数据都是从properties文件中读取的。
package jdbcpool; import com.mysql.jdbc.Connection; public interface IPool {
PooledConnection getConnection(); void createConnections(int count);
}
第二步:JdbcPool
其中JdbcPool实现了 上面的数据库连接池的接口;需要重写上面的两个方法,
package jdbcpool; import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Vector; import sun.reflect.generics.tree.Tree; import com.sun.corba.se.spi.orbutil.fsm.InputImpl; public class JdbcPool implements IPool{
public static String jdbcDriver="";
public static String dbUserName="";
public static String dbPassword="";
public static String dbUrl=""; public static int initConCount;
public static int maxConnects;
public static int inCrementalcount; private static Vector<PooledConnection> vector=new Vector<PooledConnection>();//vector当成一个池子,需要就去里面拿,pooledConnction,用来分装一个JDBCconection public void init(){
System.out.println("1");
InputStream in= JdbcPool.class.getClassLoader().getResourceAsStream("jdbcpool/jdbc.properties");
Properties pt= new Properties();
try {
pt.load(in);
} catch (IOException e) {
e.printStackTrace();
}
jdbcDriver=pt.getProperty("jdbcDriver");
dbUserName=pt.getProperty("dbUserName");
dbPassword=pt.getProperty("dbPassword");
dbUrl=pt.getProperty("dbUrl");
initConCount=Integer.valueOf(pt.getProperty("initConCount")) ;
maxConnects=Integer.valueOf(pt.getProperty("maxConnects")) ;
inCrementalcount=Integer.valueOf(pt.getProperty("inCrementalcount")) ; try {
Driver driver=(Driver)(Class.forName(jdbcDriver).newInstance());
DriverManager.registerDriver(driver);//载入JDBC驱动,连接的时候以后不用再加载驱动了
createConnections(initConCount);//初始化连接池中数据
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
} public synchronized PooledConnection getConnection() {
if(vector.size()<=0){//拿连接的时候,首先应该判定池子中有没有数据,没有错误就应该抛出对应的一个错误信息
System.out.println("连接池中还没有连接");
throw new RuntimeException("连接池中还没有连接");
}
PooledConnection conn = getActionConnection();//得到数据库连接
if(conn==null){//连接池中的连接全部为忙碌状态, 这个时候要扩容//的到连接后首先应该判定连接有没有拿到,没到那就为null,拿到了就直接返回
//这个时候需要对连接池进行增长
createConnections(inCrementalcount);//没有了就根据对应的步长去拿
conn=getActionConnection();//有没有再次为Null 多个线程拿连接,Vector 为单例,内存中只有一份,一直拿不到,所以为Null
while(conn==null){//如果没有拿到,就无线循环
try {
Thread.sleep(300);//每次循环休息300
} catch (InterruptedException e) {
e.printStackTrace();
}
conn=getActionConnection();//继续拿,迟早会拿到
}
} return conn;
}
private PooledConnection getActionConnection(){
for (PooledConnection conn : vector) {//遍历池子中封装的jdbcPool
if(!conn.isBusy()){//这个数据不忙碌
Connection trueconn=conn.getConn();//拿到这个连接
try {
if(!trueconn.isValid(0)){//拿到连接后要判定有没有超时
Connection newconn=DriverManager.getConnection(dbUrl,
dbUserName,
dbPassword);
conn.setConn(newconn);
}
} catch (SQLException e) {
e.printStackTrace();
}
conn.setBusy(true);//拿到后就必须设置为忙碌
return conn;
}
}
return null; }
/**
* 创建连接,首先应该判定 在创建
*/
public void createConnections(int count) {
if(maxConnects>0&&vector.size()>=maxConnects){
System.out.println("连接大于最大的值");
throw new RuntimeException("连接池中的连接已经大于最大值");
}
for (int i = 0; i < count; i++) {
//创建连接时候 我们要判定是否小于最大值 try {
Connection conn=DriverManager.getConnection(dbUrl,//创建数据库的连接
dbUserName,
dbPassword);
vector.add(new PooledConnection(conn,false));//封装成自己的连接;
} catch (SQLException e) {
e.printStackTrace();
}
}
} }
第三步:新建一个PooledConnection ,用来人工封装我们的数据库连接池中的单位, this.conn=conn; this.isBusy=isBusy;isBusy为true的时候,代表该连接不可用
package jdbcpool; import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; public class PooledConnection {
private Connection conn=null; private boolean isBusy=false; public PooledConnection(Connection conn,boolean isBusy){
this.conn=conn; this.isBusy=isBusy;
} public ResultSet queryBySql(String sql){
Statement sm=null;
ResultSet rs=null;
try {
sm=conn.createStatement();
rs=sm.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return rs; }
public int updateBysql(String sql){ Statement sm=null;
int count=-1;
try{
sm=conn.createStatement();
count=sm.executeUpdate(sql);
} catch (SQLException e){
e.printStackTrace();
}
return count;
}
public Connection getConn() {
return conn;
} public void setConn(Connection conn) {
this.conn = conn;
} public boolean isBusy() {
return isBusy;
} public void setBusy(boolean isBusy) {
this.isBusy = isBusy;
}
public void close(){
isBusy=false;
} }
jdbc.properties 文件中配置参数,以后只用改这里就可以了
jdbcDriver=com.mysql.jdbc.Driver dbUrl=jdbc:mysql://localhost:3306/query dbUserName=root dbPassword=123456 initConCount=10 maxConnects=100 inCrementalcount=2
第五步:测试JdbcPoolTest
测试用的junit ,需要导入对应的架包,
package jdbcpool;
import java.sql.ResultSet; import org.junit.Before;
import org.junit.Test;
public class JdbcPoolTest {
JdbcPool pool=DbManager.getInstance();
@Before
public void before(){
pool.init();
}
@Test
public void select()throws Exception{
PooledConnection conn=pool.getConnection();
ResultSet rs=conn.queryBySql("select * from account ");
System.out.println("线程名称:"+Thread.currentThread().getName());
while(rs.next()){
System.out.print(rs.getString("id")+"\t");
System.out.print(rs.getString("account_name")+"\t");
System.out.print(rs.getString("account_pwd")+"\t\n");
}
rs.close();
conn.close();
}
@Test
public void threadTest() {
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
public void run() {
try {
select();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
} }
数据库连接池原理 与实现(动脑学院Jack老师课后自己的练习有感)的更多相关文章
- JDBC数据库连接池原理
JDBC是java数据库连接的简称.它是一种用于实行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成.其相关的API都在java.sql.*包下 ...
- Java数据库连接池原理与简易实现
1.什么是数据库连接池 我们现在在开发中一定都会用到数据库,为了提高我们的系统的访问速度,数据库优化是一个有效的途径.我们现在开发中使用数据库一般都要经历以下的四个步骤:(1)加载数据库的驱动类,(2 ...
- JAVA和C#中数据库连接池原理与应用
JAVA和C#中数据库连接池原理 在现在的互联网发展中,高并发成为了主流,而最关键的部分就是对数据库操作和访问,在现在的互联网发展中,ORM框架曾出不穷, 比如:.Net-Core的EFCore.Sq ...
- Java中数据库连接池原理机制的详细讲解以及项目连接数据库采用JDBC常用的几种连接方式
连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式 ...
- Java中数据库连接池原理机制的详细讲解
连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式 ...
- Java中数据库连接池原理机制的详细讲解(转)
连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池 (Resource Pool).该模 ...
- DBCP数据库连接池原理分析
在比较大的项目中,需要不断的从数据库中获取数据,Java中则使用JDBC连接数据库,但是获取数据库的连接可是相当耗时的操作,每次连接数据库都获得 .销毁数据库连接,将是很大的一个开销.为了解决这种开销 ...
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
作为后台服务开发,在日常工作中我们天天都在跟数据库打交道,一直在进行各种CRUD操作,都会使用到数据库连接池.按照发展历程,业界知名的数据库连接池有以下几种:c3p0.DBCP.Tomcat JDBC ...
- 装饰者模式&数据库连接池原理
装饰者模式: 我是一个没有感情的杀手 在复习到自建数据库连接池的时候有点蒙了,再次翻看视频整理如下:(装饰者模式下自建数据库连接池修改close功能为 回收连接对象) 自备材料:数据库连接对象的获取的 ...
随机推荐
- kettle系列-2.kettle源码结构分析
kettle是一个开源产品,产品本身设计是很优秀的,代码应该是很多开源爱好者用业余时间贡献的,代码整体结构还是比较容易理解的,但具体到每一个控件内部就因人而异了,感觉还是挺复杂的,肯定别人考虑得比较全 ...
- 《利用Python进行数据分析: Python for Data Analysis 》学习随笔
NoteBook of <Data Analysis with Python> 3.IPython基础 Tab自动补齐 变量名 变量方法 路径 解释 ?解释, ??显示函数源码 ?搜索命名 ...
- MXNet设计和实现简介
原文:https://github.com/dmlc/mxnet/issues/797 神经网络本质上是一种语言,我们通过它来表达对应用问题的理解.例如我们用卷积层来表达空间相关性,RNN来表达时间连 ...
- 速度最快的Json序列框架Jil,入门动手实录
好吧,我又先要贴出跑分图了,出处 Jil是一个面向Json的序列化框架,在Nuget上可以下载到 支持数据类型 值得一提的是,Guid指定带破折号格式(44B2673B-B5CA-477B-A8EA- ...
- UWP 设备分辨率
之前看了下网上,分辨率都是用webview js拿或者全屏拿宽高,很有局限性. 研究一下.找到个完美的方法: public Size GetDeviceResolution() { Size reso ...
- IOC装配Bean(注解方式)
Spring的注解装配Bean Spring2.5 引入使用注解去定义Bean @Component 描述Spring框架中Bean Spring的框架中提供了与@Component注解等效的三个注解 ...
- WEB容器启动——web.xml加载详解
最近在看spring的源码,关于web.xml文件在容器(Tomcat.JBOSS等)启动时加载顺序问题很混乱,通过搜集资料,得出以下的结论: 1.加载顺序与它们在 web.xml 文件中的先后顺序无 ...
- ASP.NET 你必须知道的EF知识和经验
原文:http://www.cnblogs.com/zhaopei/p/5721789.html
- CentOS 6.5 下 CDH 5.2.1 集群安装(一)
集群节点数量3 个 192.168.1.170 cdh-master 192.168.1.171 cdh-slave-1 192.168.1.171 cdh-slave-2 一.安装CentOS6.5 ...
- 几种经典排序算法的R语言描述
1.数据准备 # 测试数组 vector = c(,,,,,,,,,,,,,,) vector ## [] 2.R语言内置排序函数 在R中和排序相关的函数主要有三个:sort(),rank(),ord ...