本文参考:https://segmentfault.com/a/1190000013308078
连接池用于创建和管理数据库连接的缓冲池技术,缓冲池中的连接可以被任何需要他们的线程使用。当一个线程需要用JDBC对一个数据库操作时,将从池中请求一个连接。当这个连接使用完毕后,将返回到连接池中,等待为其他的线程服务。
详细可看:何为数据库连接池?其工作原理是什么?
话不多说直接贴代码
注:在这个类中封装了数据库基本的连接操作和一个最简单的insert方法以便后面进行两种情况下效率对比的实验。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @author void
* @date 2020/3/26/14:08
* 不使用数据池的数据库操作方式
*/
public class JDBCUtil {
private static String URL = null;
private static String DRIVERS = null;
private static String USERNAME = null;
private static String PASSWORD = null;
static {
try{
URL = "jdbc:mysql://localhost:3306/blog";
DRIVERS = "com.mysql.jdbc.Driver";
USERNAME = "root";
PASSWORD = "Peng1104.";
Class.forName(DRIVERS);
}catch (Exception e){
e.printStackTrace();
}
}
// 通过DriverManger获取连接对象
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(URL,USERNAME,PASSWORD);
}
public static void insert(String sql, Connection conn, PreparedStatement pre){
try {
pre = conn.prepareStatement(sql);
pre.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void clear(Connection conn, PreparedStatement pre){
try {
if(pre != null){
pre.close();
}
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
注:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.LinkedList;
/**
* @author void
* @date 2020/3/26/11:11
*/
public class JDBCPoolUtil {
private static LinkedList<Connection> list = new LinkedList<>();
static {
try{
final String URL = "jdbc:mysql://localhost:3306/blog";
final String DRIVERS = "com.mysql.jdbc.Driver";
final String USERNAME = "root";
final String PASSWORD = "Peng1104.";
Class.forName(DRIVERS);
for(int i = 0; i < 10; i++){
Connection connection = DriverManager.getConnection(URL,USERNAME,PASSWORD);
list.add(connection);
}
}catch (Exception e){
e.printStackTrace();
}
}
// 从数据池获取连接的方法
public static Connection getConnection() throws SQLException{
if(list.size() > 0){
final Connection connection = list.removeFirst();
System.out.println("池中还有 "+list.size()+" 空闲连接可用");
// 动态代理JDBCPoolUtil中的Close方法
return (Connection) Proxy.newProxyInstance(JDBCPoolUtil.class.getClassLoader(), connection.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 只对close方法进行代理
if(method.getName().equals("close")){
// 将连接归还到连接池中
list.add(connection);
System.out.println("此时,池中还有 "+ list.size() +" 空闲连接可用");
}else{
return method.invoke(connection, args);
}
return null;
}
});
}
return null;
}
public static void insert(PreparedStatement pre){
try {
pre.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void clear(Connection conn, PreparedStatement pre){
try {
if(pre != null){
pre.close();
}
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
进行对照实验,比较是否使用数据池对数据库操作效率的影响,
注:比较的是每次操作新建连接和事先建好连接每次从数据池里取的区别。所以每次操作都要释放连接
import java.sql.*;
/**
* @author void
* @date 2020/3/25/1:31
*/
public class Main {
public static void main(String[] args) {
String sql = "insert into user values(null,'hello','123','[email protected]','456')";
Long startTime = System.currentTimeMillis();
for(int i = 0; i < 10; i++){
try {
Connection conn = JDBCUtil.getConnection();
PreparedStatement pre = conn.prepareStatement(sql);
JDBCUtil.insert(sql,conn,pre);
// 释放资源
JDBCUtil.clear(conn,pre);
}catch (Exception e){
e.printStackTrace();
}
}
Long endTime = System.currentTimeMillis();
System.out.println("不使用连接池耗时:"+ (endTime - startTime) +"毫秒");
Long startTime1 = System.currentTimeMillis();
for (int i = 0; i < 10; i++){
try {
Connection conn = JDBCPoolUtil.getConnection();
PreparedStatement pre = conn.prepareStatement(sql);
JDBCPoolUtil.insert(pre);
// 释放资源
JDBCPoolUtil.clear(conn,pre);
} catch (SQLException e) {
e.printStackTrace();
}
}
Long endTime1 = System.currentTimeMillis();
System.out.println("使用连接池耗时:"+ (endTime1 - startTime1) +"毫秒");
}
}
最后将JDBCPoolUtil类中打印的两句话注释掉,比较两种方法的耗时
操作次数 | (耗时)不使用连接池 | (耗时)使用连接池 |
---|---|---|
10 | 475毫秒 | 164毫秒 |
100 | 942毫秒 | 354毫秒 |
1000 | 4800毫秒 | 1719毫秒 |
10000 | 34579毫秒 | 14614毫秒 |
可以得知,在没有任何其他优化的情况下,使用数据池已经是肉眼可见的快了