博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据库连接池,实现及分析
阅读量:6504 次
发布时间:2019-06-24

本文共 6160 字,大约阅读时间需要 20 分钟。

在我们日常对数据库操作时存在一个问题,要为每次数据操作请求建立一个数据库连接。而每次建立连接都需要花费很多开销,如加载驱动类、注册驱动、获取连接,这样如果在短时间内连接多次,就

会耗费多余的时间(加载驱动+注册驱动)*n次;
在这里插入图片描述
那么就有了数据库连接池这种解决方案:
在这里插入图片描述
这样就节省了很多时间。而关闭数据连接与上面是一样的,就不再画了。下面是用java实现数据库连接池并分析两种方式的时间消耗:

首先是DBconnectPool.java,相当于把业务都抽象出来

package Pool;import java.util.*;import java.sql.*;/** * 项目名: CSDN 包名: Pool 文件名: DBconnectPool.java 创建时间: 2019年4月14日 *  * @author: xiatom 描述:建立数据连接池 *  * **/public class DBconnectPool {	// 可用数据库连接,也就是数据连接池,因为要线程安全所以使用Vector	private Vector
freeConnection = new Vector<>(); private int maxConn;// 最大连接数 private int normalConn;// 保持连接数 private String pass; private String user; private String url; private int numActive = 0;// 当前活动连接数 private static int num = 0;// 当前空闲连接数 public DBconnectPool(String url, String user, String pass, int maxConn, int normalConn) { this.user = user; this.url = url; this.pass = pass; this.maxConn = maxConn; this.normalConn = normalConn; for (int i = 0; i < normalConn; i++) { Connection con = newConnection(); if (con != null) { freeConnection.addElement(con); num++; } } } //新建连接,也就是第二张图的小格子。省去每次加载注册驱动时间 private Connection newConnection() { Connection con = null; try { if (user == null) con = DriverManager.getConnection(url); else con = DriverManager.getConnection(url, user, pass); System.out.println("新建一个数据库链接"); } catch (SQLException e) { System.out.println("新建数据库链接失败,错误:" + e); return null; } return con; } //获取当前空闲连接 public int getNum() { return num; } //获取当前使用连接 public int getNumActive() { return numActive; } public synchronized Connection getConnection() { Connection con = null; System.out.println(Thread.currentThread().getName() + "开始获取数据库链接"); if (freeConnection.size() > 0) { num--; con = freeConnection.elementAt(0); freeConnection.removeElementAt(0); // 未考虑在数据池中已关闭的连接,若考虑需要自己加 } else if (maxConn == 0 || normalConn < maxConn) { con = newConnection(); } if (con != null) System.out.println(Thread.currentThread().getName() + "获取到一个数据库链接"); else System.out.println("得到空的数据库连接"); numActive++; return con; } public synchronized void freeConnection(Connection con) { freeConnection.addElement(con); num++; numActive--; notifyAll(); } //关闭所有的连接 public synchronized void release() { for (Connection con : freeConnection) { try { con.close(); num--; System.out.println("关闭一个数据库链接"); } catch (SQLException e) { System.out.println("释放数据链接池失败"); } } if (num == 0) System.out.println("释放所有链接"); freeConnection.removeAllElements(); numActive = 0; }}

下面是Pool.java,实现数据库连接池:

package Pool;import java.sql.Connection;import java.sql.Driver;import java.sql.DriverManager;import java.sql.SQLException;/** * 项目名: CSDN 包名: Pool 文件名: Pool.java 创建时间: 2019年4月15日 *  * @author: xiatom 描述: *  * **/public class Pool {	private static Pool instance = null;	private int maxConn = 100;	private int normalConn = 10;	private String password = "1023";	private String user = "root";	private String url = "jdbc:mysql://localhost:3306/test";	private String driverName = "com.mysql.jdbc.Driver";	DBconnectPool dbpool = null;	Driver dbDriver = null;	private Pool() {		loadDriver(driverName);		createPool();	}	private void createPool() {		dbpool = new DBconnectPool(url, user, password, maxConn, normalConn);	}	private void loadDriver(String driver) {		try {			dbDriver = (Driver) Class.forName(driver).newInstance();			// DriverManager.registerDriver(dbDriver);			System.out.println("注册驱动类" + driver + "成功");		} catch (Exception e) {			System.out.println("无法注册驱动类" + driver + " 错误:" + e);		}	}	public void freeCon(Connection con) {		if (con != null) {			dbpool.freeConnection(con);			System.out.println("释放成功");		} else			System.out.println("传递的是一个空连接");	}	public static Pool getInstance() {		if (instance == null)			instance = new Pool();		return instance;	}	public Connection getCon() {		return dbpool.getConnection();	}	public int getNum() {		return dbpool.getNum();	}	public int getNumActive() {		return dbpool.getNumActive();	}	public synchronized void release() {		dbpool.release();		try {			DriverManager.registerDriver(dbDriver);			System.out.println("撤销驱动成功");		} catch (SQLException e) {			System.out.println("撤销驱动失败");			e.printStackTrace();		}	}}

上面synchronized关键字是为了保证线程安全加的锁

如果没有锁:举个例子DBconnectPool类的getConnection方法

num--;			con = freeConnection.elementAt(0);如果不加锁,则有两个线程获取连接时,都执行到上面那一步,那么他们获取的是同一个连接,因为这时freeConnection并没有发生改变,首元素是一样的。然后他们在都执行下面这句			freeConnection.removeElementAt(0);就会导致两个线程用的同一个连接,然后连接池丢失了一个链接

下面是依照此方法,建立10个数据连接耗费的时间

package Pool;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;/*** 项目名:		CSDN* 包名:		Pool* 文件名:		MutiThreadTest.java* 创建时间:	2019年4月15日* * @author:	xiatom* 描述:		* ***/public class ThreadTest implements Runnable{	static Pool pool = null;		public void test() {			}		@Override	public void run() {		Connection con = pool.getCon();		System.out.println("剩余"+pool.getNum()+"个可用连接");	}		public static void main(String[] args) {		pool = Pool.getInstance();		ThreadTest tt = new ThreadTest();		Thread t[] = new Thread[10];		long start = System.currentTimeMillis();		for(int i=0;i<10;i++) {			new Thread(tt,"Thread-"+(i+1)).start();		}		while(pool.getNum()!=0) {		}			try {			Thread.sleep(1);		} catch (InterruptedException e) {			e.printStackTrace();		}		System.out.println("使用时间:"+(System.currentTimeMillis()-start));	}}

在这里插入图片描述

在这里插入图片描述
由于我为了等所有线程结束所以多用了1毫秒去等待,所以实际使用时间为3毫秒左右。

下面是常规方法,建立数据连接:

import java.sql.*;public class Connect {	private Connection connection;	Connect() {		try {			Class.forName("com.mysql.jdbc.Driver");			String url = "jdbc:mysql://localhost:3306/test";			this.connection = DriverManager.getConnection(url,"root","1023");		} 		catch (ClassNotFoundException | SQLException e) {			e.printStackTrace();		}	}	public Connection getCon() {		return this.connection;	}}

测试类

import java.sql.*;public class Main {	public static void main(String[] args) throws SQLException {		long start = System.currentTimeMillis();		for(int i=0;i<10;i++) {			new Connect().getCon();		}		long end = System.currentTimeMillis()-start;		System.out.println("消耗时间:"+end);	}}

在这里插入图片描述

差距就很明显了。

转载于:https://www.cnblogs.com/xiatom/p/10784849.html

你可能感兴趣的文章
MYSQL体系结构-来自期刊
查看>>
mysql的基本知识
查看>>
webpack入门(二)what is webpack
查看>>
UnitOfWork以及其在ABP中的应用
查看>>
学习C语言必须知道的理论知识(第一章)
查看>>
for语句内嵌例题与个人理解
查看>>
眠眠interview Question
查看>>
[转]CSS hack大全&详解
查看>>
RPC-client异步收发核心细节?
查看>>
#define WIN32_LEAN_AND_MEAN 的作用
查看>>
仿余额宝数字跳动效果 TextCounter
查看>>
你必须知道的.net学习总结
查看>>
Axure8.0 网页 or App 鼠标滚动效果
查看>>
文件操作示例脚本 tcl
查看>>
大家好,新年快乐。
查看>>
prototype
查看>>
Android学习路线
查看>>
Linux下的redis的持久化,主从同步及哨兵
查看>>
在相同的主机上创建一个duplicate数据库
查看>>
Date15
查看>>