https://blog.csdn.net/qq_16038125/article/details/80180941

池:同一类对象集合

连接池的作用 
1. 资源重用 
由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。 
2. 更快的系统响应速度 
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。 
3. 新的资源分配手段 
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,使用数据库连接池技术。设置某一应用最大可用数据库连接数,避免某一应用独占所有数据库资源。 
4. 统一的连接管理,避免数据库连接泄漏 
在较为完备的数据库连接池实现中,可根据预先设定的连接占用超时时间,强制收回被超时占用的连接。从而避免了常规数据库连接操作中可能出现的资源泄漏(当程序存在缺陷时,申请的连接忘记关闭,这时候,就存在连接泄漏了)。

示例

配置文件

jdbcDriver=com.mysql.jdbc.Driver
jdbcurl=jdbc:mysql://localhost:3306/mybatis
userName=root
password=root
initCount=10
stepSize=4
poolMaxSize=150

数据库连接封装

public class PooledConnection {
private boolean isBusy = false;
private Connection connection; public Connection getConnection() {
return connection;
} public void setConnection(Connection connection) {
this.connection = connection;
} public boolean isBusy() {
return isBusy;
} public void setBusy(boolean isBusy) {
this.isBusy = isBusy;
} public PooledConnection(Connection connection, boolean isBusy) {
this.connection = connection;
this.isBusy = isBusy;
} public void close() {
this.isBusy = false;
} public ResultSet queryBysql(String sql) {
Statement sm = null;
java.sql.ResultSet rs = null; try {
sm = connection.createStatement();
rs = sm.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
} return rs;
} }

连接池接口

public interface IMyPool {

    PooledConnection getConnection();

    void createConnection(int count);
}

实现

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; public class MyPoolImpl implements IMyPool { private static String jdbcDriver = null;
private static String jdbcUrl = null;
private static String userName = null;
private static String password = null; private static int initCount; private static int stepSize; private static int poolMaxSize; private static Vector<PooledConnection> pooledConnections = new Vector<>(); public MyPoolImpl() { init();
} private void init() { InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("jdbc.properties"); //字节信息 key value 形式化
Properties pro = new Properties();
try {
pro.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
} jdbcDriver = pro.getProperty("jdbcDriver");
jdbcUrl = pro.getProperty("jdbcurl");
userName = pro.getProperty("userName");
password = pro.getProperty("password"); initCount = Integer.valueOf(pro.getProperty("initCount"));
stepSize = Integer.valueOf(pro.getProperty("stepSize"));
poolMaxSize = Integer.valueOf(pro.getProperty("poolMaxSize")); try {
Driver mysqlDriver = (Driver) Class.forName(jdbcDriver).newInstance(); DriverManager.registerDriver(mysqlDriver); createConnection(initCount); } catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} } public PooledConnection getConnection() {
if (pooledConnections.size() == 0) {
System.out.println("获取链接管道失败,原因是连接池中没有可用管道");
throw new RuntimeException("创建管道对象失败,原因是即将超过最大上限值");
}
//连接池中的管道是没有超时 没有其他线程占用
PooledConnection connection = getRealConnection(); while (connection == null) {
createConnection(stepSize);
connection = getRealConnection();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return connection;
} @Override
public void createConnection(int count) {
if (poolMaxSize > 0 && pooledConnections.size() + count > poolMaxSize) {
System.out.println("创建管道对象失败,原因是即将超过最大上限值");
throw new RuntimeException("创建管道对象失败,原因是即将超过最大上限值");
} for (int i = 0; i < count; i++) {
try {
Connection conn = DriverManager.getConnection(jdbcUrl, userName, password); PooledConnection pooledConnection = new PooledConnection(conn, false);
pooledConnections.add(pooledConnection);
} catch (SQLException e) {
e.printStackTrace();
} }
} private synchronized PooledConnection getRealConnection() {
for (PooledConnection conn : pooledConnections) {
if (!conn.isBusy()) {
Connection connection = conn.getConnection();
try { //发送一个信息给数据库 2000毫秒内 收到返回信息 认为 这个管道没有超时
if (!connection.isValid(2000)) {
Connection validConn = DriverManager.getConnection(jdbcUrl, userName, password);
conn.setConnection(validConn);
}
} catch (SQLException e) {
e.printStackTrace();
}
conn.setBusy(true);
return conn;
}
}
return null;
} }

连接池管理

public class PoolManager {

    private static class createPool {

        private static MyPoolImpl poolImpl = new MyPoolImpl();

    }

    /**
* 内部类单利模式产生使用对象
* @return
*/
public static MyPoolImpl getInstance() {
return createPool.poolImpl;
}
}

测试类

import java.sql.ResultSet;
import java.sql.SQLException; public class MypoolTest { private static MyPoolImpl poolImpl = PoolManager.getInstance(); public synchronized static void selctData() {
PooledConnection connection = poolImpl.getConnection();
ResultSet rs = connection.queryBysql("SELECT * FROM user");
try {
while (rs.next()) {
System.out.println(rs.getString("ID") + "\t\t");
System.out.println(rs.getString("USERNAME") + "\t\t");
System.out.println(rs.getString("PASSWORD") + "\t\t");
System.out.println();
}
rs.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
} } public static void main(String[] args) {
for (int i = 0; i < 1500; i++) {
new Thread(new Runnable() {
@Override
public void run() {
selctData();
}
}).start();
}
} }

java设计思想-池化-手写数据库连接池的更多相关文章

  1. 关于利用动态代理手写数据库连接池的异常 java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to java.sql.Connection

    代码如下: final Connection conn=pool.remove(0); //利用动态代理改造close方法 Connection proxy= (Connection) Proxy.n ...

  2. 手写线程池,对照学习ThreadPoolExecutor线程池实现原理!

    作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...

  3. Go组件学习——手写连接池并没有那么简单

    1.背景 前段时间在看gorm,发现gorm是复用database/sql的连接池. 于是翻了下database/sql的数据库连接池的代码实现,看完代码,好像也不是很复杂,但是总觉得理解不够深刻,于 ...

  4. 使用java语言基于SMTP协议手写邮件客户端

    使用java语言基于SMTP协议手写邮件客户端 1. 说明 电子邮件是互联网上常见的应用,他是互联网早期的产品,直至今日依然受到广大用户的喜爱(在中国可能因为文化背景不同,电子邮件只在办公的时候常用) ...

  5. 【Java EE 学习 15】【自定义数据库连接池之动态代理的使用】

    一.动态代理的作用 使用动态代理可以拦截一个对象某个方法的执行,并执行自定义的方法,其本质是反射 优点:灵活 缺点:由于其本质是反射,所以执行速度相对要慢一些 二.数据库连接池设计思想 1.为什么要使 ...

  6. 【Java EE 学习 16 上】【dbcp数据库连接池】【c3p0数据库连接池】

    一.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: package day16.utils; import java.io.IOException; import java.lang.ref ...

  7. java基础之JDBC六:DBCP 数据库连接池简介

    我们之前写的代码中的数据库连接每次都是自己创建,用完以后自己close()销毁的,这样是很耗费资源的,所以我们引入DBCP DBCP简介 概述: Data Base Connection Pool, ...

  8. java - day016 - IO续(输入输出), 手写双向链表

    课程回顾 对象的创建过程 类加载 加载父类,父类的静态变量分配内存 加载子类,子类的静态变量分配内存 父类静态变量赋值运算, 和静态初始化块 子类静态变量赋值运算, 和子类初始化块 创建对象 创建父类 ...

  9. java手写线程池,完善中

    package com.test001.threadpool; import java.util.LinkedList; import java.util.List; import java.util ...

随机推荐

  1. 通过100张图一步步理解CNN

    https://blog.csdn.net/v_july_v/article/details/79434745 Youtube上迄今为止最好的卷积神经网络快速入门教程 https://www.bili ...

  2. 文件夹上传控件webupload插件

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...

  3. 可以使用WinDbg将PE映像作为转储文件打开

    WinDbg.ntsd.cdb.kd和其他任何使用DbgEng打开转储文件的工具都有一个鲜为人知的特性.事实证明,使用DbgEng提供的任何功能,在任何可以打开转储文件(用户转储.内核转储等)的地方, ...

  4. /proc文件系统的特点和/proc文件的说明

    /proc文件系统是一种特殊的.由软件创建的文件系统,内核使用它向外界导出信息,/proc系统只存在内存当中,而不占用外存空间. /proc下面的每个文件都绑定于一个内核函数,用户读取文件时,该函数动 ...

  5. 鸿蒙OS与手机系统

    鸿蒙发布会上,华为只是说手机端能很快切换到鸿蒙上,但并没有将切换到手机端放到计划表.如果不出意外,手机会是最后用上鸿蒙的终端,尽管它是现在对人们最重要.应用最多.也是人们讨论最多希望鸿蒙迁移到的终端. ...

  6. spring的重试策略、发生异常会自动重新调用

    测试类以及测试代码.复制即可 package com.cms.util; import javax.swing.plaf.synth.SynthSpinnerUI; import org.spring ...

  7. thrift 是rpc协议

    PC(Remote Procedure Call,远程过程调用)是建立在Socket之上的,出于一种类比的愿望,在一台机器上运行的主程序,可以调用另一台机器上准备好的子程序,就像LPC(本地过程调用) ...

  8. ubuntu之路——day17.4 卷积神经网络示例

    以上是一个识别手写数字的示例 在这个示例中使用了两个卷积-池化层,三个全连接层和最后的softmax输出层 一般而言,CNN的构成就是由数个卷积层紧跟池化层再加上数个全连接层和输出层来构建网络. 在上 ...

  9. 【面向对象】第三单元总结——JML

    梳理JML语言的理论基础.应用工具链情况 JML语言理论基础 JML(Java Modeling Language)是一种行为规范接口语言,通过使用不会被编译的注释形式,和固定关键字的语法,指定Jav ...

  10. 禁用wordpress新编辑器,使用经典编辑器的方法

    新更新的wordpress推出勒个什么古腾堡编辑器?简直太难用了,怎么屏蔽古腾堡编辑器,如何使用wordpress的经典编辑器.有人说使用插件,比如ClassicEditor或者DisableGute ...