java写一个简单的jdbc数据库连接池
一、实现原理
1、声明一个静态的变量 public static Vector<Connection> pools
2、将获取到的 java.sql.Connection 对象添加到 pools 中
3、获取的 Connection 对象将 Vector 池中移除
4、释放资源将Connection对象放回 Vector 池中
二、代码实现
1、写一个简单的连接池 PoolUtils.java
package com.xx.xx;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;
/**
* @description: 写一个简单的连接池
* @author w
* @date 2018年8月7日 16:50:54
*/
public class PoolUtils {
private static Vector<Connection> pools ;
private static Integer poolSize = 10 ;
private static PoolUtils instance ;
public static final String URL = "jdbc:mysql://localhost:3306/chapter";
public static final String USER = "root";
public static final String PWD = "123";
/**
* 构造方法私有化,避免外部 直接new 获取当前对象实例。
*/
private PoolUtils() {
init();
}
/**
* 获取当前类石例 --- 单例 懒汉式
* @return
*/
public synchronized static PoolUtils getInstance(){
if(null == instance){
instance = new PoolUtils();
}
return instance;
}
/**
* 初始化连接池
*/
private void init(){
pools=new Vector<>(poolSize);
for (int i = 0; i < poolSize; i++) {
Connection c = null;
try {
c = DriverManager.getConnection(URL,USER,PWD);
} catch (SQLException e) {
e.printStackTrace();
}
pools.add(c);
}
}
/**
* 获取一个连接对象
* synchronized : 避免多线程环境下,同一个连接被获取多次
* @return
*/
public synchronized Connection getConnection(){
if(pools.size() > 0){
return pools.remove(0);
}
return null ;
}
/**
* 释放链接资源
* @param conn
*/
public void release(Connection conn){
if(conn != null){
pools.add(conn);
}
}
/**
* 获取连接池剩余的连接数
* @return
*/
public static int getPoolsSize(){
if(!pools.isEmpty()){
return pools.size();
}
return 0;
}
/**
* 直接获取连接,不使用连接池
* @param i 站位 ,实现重载
* @return
*/
public static Connection getConnection(int i){
try {
Connection connection = DriverManager.getConnection(URL,USER,PWD);
return connection;
} catch (SQLException e) {
e.printStackTrace();
}
return null ;
}
}
三、测试 --- 连接池和直接获取连接
1、比较使用连接池和直接获取连接对象执行效率情况
package com.xx.xx;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 针对数据库连接池获取连接和直接获取连接 执行查询情况,效率对比。
* @author w
*/
public class PoolTest {
public static void main(String[] args) {
// 执行查询的次数
int sum = 100;
long start = System.currentTimeMillis();
poolsExecute(sum);
System.out.println("使用连接池耗时:"+(System.currentTimeMillis()-start)+" ms");
start = System.currentTimeMillis();
connExecute(sum);
System.out.println("直接获取连接耗时:"+(System.currentTimeMillis()-start)+" ms");
}
/**
* 使用连接池,获取连接,执行查询
* @param sum
*/
private static void poolsExecute(int sum) {
for (int i = 0; i < sum; i++) {
Connection connection = PoolUtils.getInstance().getConnection();
try {
query(connection,sum);
} catch (Exception e) {
e.printStackTrace();
}finally{
// 释放资源
PoolUtils.getInstance().release(connection);
}
}
}
/**
* 直接获取连接,不使用连接池 执行查询
* @param sum 占位符
*/
private static void connExecute(int sum) {
for (int i = 0; i < sum; i++) {
Connection connection = PoolUtils.getConnection(sum);
query(connection,sum);
// 增加是否关闭连接,测试耗时情况
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 具体执行查询的方法
* @param connection 数据库连接对象
* @param sum 占位符
*/
private static void query(Connection connection,int sum) {
String sql = "SELECT * from client limit 1";
try {
PreparedStatement prepareStatement = connection.prepareStatement(sql);
ResultSet resultSet = prepareStatement.executeQuery();
while(resultSet.next()){
String id = resultSet.getString("id");
String name = resultSet.getString("name");
// System.out.println("id :"+id + " name: "+name);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
四、测试结果
1、使用连接池耗时:1615 ms
2、直接获取连接耗时:5947 ms
3、结论: 连接池可以极大查询效率,避免每次都获取连接对象,从而造成资源浪费。 本连接池以极简的方式实现,便于理解。 因使用的jdk1.7 ,可以省略加载数据库驱动部分。(Class.forName("com.mysql.jdbc.Driver");)
4、可优化部分: 数据库资料改到配置文件中;测试连接池对象足够时,可开启多线程执行查询,充分利用资源。 本示例测试代码中,只用了连接池中一个连接对象。 。。。。 等等。。