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、可優化部分: 數據庫資料改到配置文件中;測試連接池對象足夠時,可開啓多線程執行查詢,充分利用資源。 本示例測試代碼中,只用了連接池中一個連接對象。 。。。。 等等。。