第一步: 首先创建一个数据库连接池的接口:

    数据库连接池接口有两个主要的方法,其中一个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老师课后自己的练习有感)的更多相关文章

  1. JDBC数据库连接池原理

    JDBC是java数据库连接的简称.它是一种用于实行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成.其相关的API都在java.sql.*包下 ...

  2. Java数据库连接池原理与简易实现

    1.什么是数据库连接池 我们现在在开发中一定都会用到数据库,为了提高我们的系统的访问速度,数据库优化是一个有效的途径.我们现在开发中使用数据库一般都要经历以下的四个步骤:(1)加载数据库的驱动类,(2 ...

  3. JAVA和C#中数据库连接池原理与应用

    JAVA和C#中数据库连接池原理 在现在的互联网发展中,高并发成为了主流,而最关键的部分就是对数据库操作和访问,在现在的互联网发展中,ORM框架曾出不穷, 比如:.Net-Core的EFCore.Sq ...

  4. Java中数据库连接池原理机制的详细讲解以及项目连接数据库采用JDBC常用的几种连接方式

    连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式 ...

  5. Java中数据库连接池原理机制的详细讲解

    连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式 ...

  6. Java中数据库连接池原理机制的详细讲解(转)

    连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池 (Resource Pool).该模 ...

  7. DBCP数据库连接池原理分析

    在比较大的项目中,需要不断的从数据库中获取数据,Java中则使用JDBC连接数据库,但是获取数据库的连接可是相当耗时的操作,每次连接数据库都获得 .销毁数据库连接,将是很大的一个开销.为了解决这种开销 ...

  8. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析

    作为后台服务开发,在日常工作中我们天天都在跟数据库打交道,一直在进行各种CRUD操作,都会使用到数据库连接池.按照发展历程,业界知名的数据库连接池有以下几种:c3p0.DBCP.Tomcat JDBC ...

  9. 装饰者模式&数据库连接池原理

    装饰者模式: 我是一个没有感情的杀手 在复习到自建数据库连接池的时候有点蒙了,再次翻看视频整理如下:(装饰者模式下自建数据库连接池修改close功能为 回收连接对象) 自备材料:数据库连接对象的获取的 ...

随机推荐

  1. 编译带有PROJ4和GEOS模块的GDAL

    1.下载三个软件的源代码(去各自官网下载即可) 2.将PROJ4和GEOS的源码放到GDAL目录下的supportlibs文件夹中. 3.修改GDAL的nmake.opt文件,部分内容如下: # Un ...

  2. python_配置

    代码示例:https://pan.baidu.com/s/1pLjLPSv 1.自动补全功能 许多人都知道 iPython 有很好的自动补全能力,但是就未必知道 python 也同样可以 Tab 键补 ...

  3. LeetCode之371. Sum of Two Integers

    ---------------------------------- 使用位运算实现加法: a^b 加不同部分(a&b)<<1 加相同部分递归相加 AC代码: public cla ...

  4. Cycles渲染研究测试效果图

    从左到右:.贴图镂空透明  2.纹理半透明  3.纹理  4.材质半透明  5.材质 输入输出节点信息如下: ############################################# ...

  5. linq学习笔记

    最近在学习linq的一些基础知识,看了c#高级编程及阅读了园子内部几篇优秀的博文,有所体会,感觉应该记录下来,作为以后复习使用.都是一些最基础的知识,大致分为三个部分:linq预备知识:linq查询: ...

  6. 关于MFi认证你所必须要知道的事情

    MFiLogo 前面我写了一篇文章<iOS App连接外设的几种方式>,其中EAP和NCM是都需要做MFi认证.对于苹果的MFI认证,对iOS开发的同学来说其实是一个比较陌生并且繁琐的to ...

  7. WSDL项目----操作和请求

    至于现在你只看服务相关的特性,让我们尝试更多的操作和相应的请求. 操作 每个基于WSDL服务公开的操作包括一个请求和响应消息格式(可选). soapUI服务中的动作显示为节点在项目导航器的服务下 在s ...

  8. POJ 2386 题解

    Lake Counting 描述 Due to recent rains, water has pooled in various places in Farmer John's field, whi ...

  9. html 之input标签height设置问题

    今天针对这个问题纠结了很久 <input type="button" value="xx" style="height:99px;" ...

  10. jquery mobile页面跳转缓存问题解决

    最近,我的一个写后端的同事因为缺前端自己做起了前端的活儿,因为对前端的不熟悉,找寻了一些现成框架想轻松了事,做一个web app他选了jquery mobile,开发效率确实高,但是这个框架的一些坑也 ...