1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > JDBC中数据库连接池的使用与传统方式的比较

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

时间:2020-06-21 18:12:10

相关推荐

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

数据库连接的传统方式

当有多个线程,每个线程都需要连接数据库执行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条数据,比较传统方式和数据库连接池方式的性能差异

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

使用数据库连接池的方式,创建一个有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倍的时间。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。