数据库连接的传统方式

当有多个线程,每个线程都需要连接数据库执行SQL语句的话,那么每个线程都会创建一个连接,并且在使用完毕后,关闭连接。创建连接和关闭连接的过程也是比较费时间的,当多线程并发的时候,系统就会变得卡顿。并且,一个数据库同时支持的连接综述也是有限的,如果多线程并发量很大,那么数据库连接的总数就会被消耗光,后续线程发起的数据库连接就会失效。

数据库连接池原理-使用池

与传统方式不同,连接池在使用之前,就会创建好一定数量的连接。
如果有任何线程需要使用连接,那么就从连接池里面借用而不是自己重新创建.
使用完毕后,又把这个连接归还给连接池供下一次或者其他线程使用。
倘若发生多线程并发情况,连接池里的连接被借用光了,那么其他线程就会临时等待,直到有连接被归还回来,再继续使用。
整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。

ConnectionPool构造方法和初始化

1.ConnectionPool()构造方法规定连接池一共有多少连接

2.在init() 初始化方法中,创建了size条连接。 注意,这里不能使用try-with-resource这种自动关闭连接的方式,因为连接恰恰需要保持不关闭状态,供后续循环使用

3.getConnection(), 判断是否为空,如果是空的就wait等待,否则就借用一条连接出去

4.returnConnection(), 在使用完毕后,归还这个连接到连接池,并且在归还完毕后,调用notifyAll,通知那些等待的线程,有新的连接可以借用了

package jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;public class ConnectionPool {List<Connection> cs = new ArrayList<Connection>();int size;public ConnectionPool(int size) {this.size = size;init();}public void init() {//这里恰恰不能使用try-with-resource的方式,因为这些连接都需要是"活"的,不要被自动关闭了try {Class.forName("com.mysql.jdbc.Driver");for (int i = 0; i < size; i++) {Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root", "admin");cs.add(c);}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public synchronized Connection getConnection() {while (cs.isEmpty()) {try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}Connection c = cs.remove(0);return c;}public synchronized void returnConnection(Connection c) {cs.add(c);this.notifyAll();}}

测试类

首先初始化一个有3条连接的数据库连接池
然后创建100个线程,每个线程都会从连接池中借用连接,并且在借用之后,归还连接。 拿到连接之后,执行一个耗时1秒的SQL语句。

运行程序,就可以观察到如图所示的效果

使用例子来比较传统方式和数据库连接池的性能差异

向数据库中插入100条数据,比较传统方式和数据库连接池方式的性能差异

  1. 使用传统方式创建100个线程,每个线程都会创建新的连接,通过这个连接向数据库插入1条数据,然后关闭这个连接。

  2. 使用数据库连接池的方式,创建一个有10条连接的连接池,然后创建100个线程,每个线程都会向连接池借用连接,借用到后,向数据库插入1条数据,然后归还这个连接。

通过时间统计,比较这两种方式的性能表现差异。


package jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;/**
使用传统方式,建立连接的线程
*/
class TraditionalWorkingThread extends Thread {public void run() {try {Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/LOL?characterEncoding=UTF-8","root", "admin"); Statement st = c.createStatement()) {for (int i = 0; i < TestConnectionPool.insertTime; i++) {String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";st.execute(sql);}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
package jdbc;import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;/*
使用连接池方式,建立连接的工作线程
*/
class ConnectionpoolWorkingThread extends Thread {private ConnectionPool cp;public ConnectionpoolWorkingThread(ConnectionPool cp) {this.cp = cp;}public void run() {Connection c = cp.getConnection();try (Statement st = c.createStatement()) {for (int i = 0; i < TestConnectionPool.insertTime; i++) {String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";st.execute(sql);}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}cp.returnConnection(c);}
}

package jdbc;import java.util.ArrayList;
import java.util.List;/**
测试类,在这个类中分别创建了100个TraditionalWorkingThread 和100ConnectionpoolWorkingThread ,并分别统计他们运行需要的时间
*/
public class TestConnectionPool {private static int threadNumber = 100;public static int insertTime = 1;public static void main(String[] args) {traditionalWay();connectionPoolWay();}private static void connectionPoolWay() {ConnectionPool cp = new ConnectionPool(10);System.out.println("开始连接池方式插入数据测试:");long start = System.currentTimeMillis();List<Thread> ts = new ArrayList<>();for (int i = 0; i < threadNumber; i++) {Thread t =new ConnectionpoolWorkingThread(cp);t.start();ts.add(t);}//等待所有线程结束for (Thread t : ts) {try {t.join();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}long end = System.currentTimeMillis();System.out.printf("使用连接池方式,启动%d条线程,每个线程插入%d条数据,一共耗时%d 毫秒%n",threadNumber,insertTime,end-start);}private static void traditionalWay() {System.out.println("开始传统方式插入数据测试:");long start = System.currentTimeMillis();List<Thread> ts = new ArrayList<>();for (int i = 0; i < threadNumber; i++) {Thread t =new TraditionalWorkingThread();t.start();ts.add(t);}//等待所有线程结束for (Thread t : ts) {try {t.join();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}long end = System.currentTimeMillis();System.out.printf("使用传统方式,启动%d条线程,每个线程插入%d条数据,一共耗时%d 毫秒%n",threadNumber,insertTime,end-start);}
}

当测试有100线程时,传统方式大约为1000ms,使用数据库连接池大约是500毫秒,节省了约1倍的时间。

JDBC中数据库连接池的使用与传统方式的比较相关推荐

  1. Java -- JDBC 学习--数据库连接池

    JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: 在主程序(如servlet.beans)中建立数据库连接. 进行sql操作 断开数据库连接. 这种模式开 ...

  2. Java JDBC和数据库连接池 韩顺平老师自学笔记

    JDBC和数据库连接池 JDBC 概述 基本介绍 原理示意图 代码示例 JdbcInterface 模拟Java公司提供给其它数据库厂商的接口,供给调用 TestJdbc 模拟一个类来实现数据库的调用 ...

  3. JavaWeb:JDBC之数据库连接池

    JDBC系列阅读 JavaWeb:用JDBC操作数据库 JavaWeb:JDBC之事务 JavaWeb:JDBC之数据库连接池 使用JDBC实现水果超市管理系统 1. 池参数(所有池参数都有默认值) ...

  4. 【JDBC】数据库连接池技术

    文章目录 一.数据库连接池技术 二.多种开源的数据库连接池 一.数据库连接池技术 1.数据库连接池的基本思想︰ 就是为数据库连接建立一个"缓冲池".预先在缓冲池中放入一定数量的连接 ...

  5. JDBC以及数据库连接池的使用

    文章目录 JDBC 步骤 数据库连接池 1.概念 2.接口规范方法 3.第三方数据库连接池技术 C3p0 Druid:由阿里提供 Druid工具类 JDBC 概念 ​ JDBC是sun公司提供的一套用 ...

  6. java 连接池配置_java数据库连接池配置的几种方式

    关于java数据库连接池配置的几种方式 今天遇到了关于数据源连接池配置的问题,发现有很多种方式可以配置,现总结如下,(已Mysql数据库为例) 一,Tomcat配置数据源: 方式一:在WebRoot下 ...

  7. kylin调优,项目中错误总结,知识点总结,kylin jdbc driver + 数据库连接池druid + Myba

    首先给大家分享一个巨牛巨牛的人工智能教程,是我无意中发现的.教程不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵段子,像看小说一样,哈哈-我正在学习中,觉得太牛了,所以分享给大家!点这里可以跳转 ...

  8. kylin调优,项目中错误总结,知识点总结,kylin jdbc driver + 数据库连接池druid + Mybatis项目中的整合,shell脚本执行kylin restapi 案例

    关于本篇文章的说明: 本篇文章为笔者辛苦劳作用了一整天总结出来的文档,大家阅读转发的时候请不要吝啬写上笔者:涂作权 和 原文地址. 由于笔者所在环境没有人用过kylin,笔者也是自学官网,阅读书籍 将 ...

  9. 基于JDBC的数据库连接池技术研究与应用

    引言 近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机 应用程序已从传统的桌面应用转到Web应用.基于B/S(Browser/Server)架构的3层开 ...

  10. JDBC系列(九):JDBC与数据库连接池(Druid-德鲁伊)使用步骤

    目录 1.导语(唠唠嗑~~~) 2.使用数据库连接池好处 3.Druid数据库连接池创建与使用步骤 3.1.创建连接池的步骤 3.2使用Druid数据库连接池的步骤 4.关闭资源与归还至连接池的一点说 ...

最新文章

  1. 如何让我们的vmware虚拟机上网!!
  2. Spark发布1.3.0版本
  3. 机器人 陆梅东_上海乐高创客工作坊活动顺利举行
  4. Nginx中浏览器缓存的执行流程
  5. java相遇问题_行程问题
  6. react hooks_为什么选择React Hooks,我们如何到达这里?
  7. php怎么调用dll例子,php调用dll的实例操作动画与代码分享_PHP教程
  8. 2020年进入倒计时:一波前端资源送给你~这一年,谢谢自己!
  9. HDOJ 2896 病毒侵袭(AC自动机入门)
  10. Android指定SDK编译版本
  11. MyBatis学习(一):简单的运行
  12. Java记录 -59- SortedSet
  13. 十进制、二进制、八进制、十六进制转换
  14. 开发者经验谈:如何一天时间搞定iOS游戏开发?
  15. Mac终端adb安卓刷机
  16. 如何实现thead固定不动,tbody出现垂直滚动条
  17. 【五线谱】重音记号、渐强记号、渐弱记号
  18. 我的JAVA面试经验(5年左右工作经验)
  19. 数据挖掘里的“降维”----从五阶魔方的玩法思考
  20. svn服务端和客户端下载网址

热门文章

  1. PYTHON之路(九)
  2. ASP.NET WEB API简介
  3. Java 标注(Annotation)详解
  4. 线程间的通信之wait和notify的使用
  5. 并发编程常见面试题总结三
  6. Battle Zone 战争地带
  7. String类的trim() 方法
  8. 从开发到发布一款基于Vue2x的图片预览插件
  9. idea提交本地项目到git
  10. Pandas python