java寫一個簡單的jdbc數據庫連接池

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

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章