《四 資料庫連線池原始碼》手寫資料庫連線池

x號開發者發表於2019-04-01

讀取外部配置資訊

 

//外部配置檔案資訊
public class DbBean {

    /* 連結屬性 */
    private String driverName = "com.mysql.jdbc.Driver";

    private String url = "jdbc:mysql://localhost:3306/test";

    private String userName = "root";

    private String password = "root";

    private String poolName = "thread01";// 連線池名字

    private int minConnections = 1; // 空閒池,最小連線數

    private int maxConnections = 10; // 空閒池,最大連線數

    private int initConnections = 5;// 初始化連線數

    private long connTimeOut = 1000;// 重複獲得連線的頻率

    private int maxActiveConnections = 100;// 最大允許的連線數,和資料庫對應

    private long connectionTimeOut = 1000 * 60 * 20;// 連線超時時間,預設20分鐘

    public String getDriverName() {
        return driverName;
    }

    public void setDriverName(String driverName) {
        this.driverName = driverName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPoolName() {
        return poolName;
    }

    public void setPoolName(String poolName) {
        this.poolName = poolName;
    }

    public int getMinConnections() {
        return minConnections;
    }

    public void setMinConnections(int minConnections) {
        this.minConnections = minConnections;
    }

    public int getMaxConnections() {
        return maxConnections;
    }

    public void setMaxConnections(int maxConnections) {
        this.maxConnections = maxConnections;
    }

    public int getInitConnections() {
        return initConnections;
    }

    public void setInitConnections(int initConnections) {
        this.initConnections = initConnections;
    }

    public long getConnTimeOut() {
        return connTimeOut;
    }

    public void setConnTimeOut(long connTimeOut) {
        this.connTimeOut = connTimeOut;
    }

    public int getMaxActiveConnections() {
        return maxActiveConnections;
    }

    public void setMaxActiveConnections(int maxActiveConnections) {
        this.maxActiveConnections = maxActiveConnections;
    }

    public long getConnectionTimeOut() {
        return connectionTimeOut;
    }

    public void setConnectionTimeOut(long connectionTimeOut) {
        this.connectionTimeOut = connectionTimeOut;
    }

}

 

建立資料庫連線池

 

/**
 * 資料庫連線池<br>
 * 
 * 1.初始化<br>
 * ####執行緒池核心容器 空閒執行緒數、活動執行緒數<br>
 * ###建構函式 1.1.1初始化執行緒,存放在空閒執行緒池中<br>
 * 2.獲取連線 <br>
 * ####1.判斷存線上程數是否大於最大執行緒 如果大於最大執行緒數,則進行等待...<br>
 * ####2.判斷空閒執行緒數是否大於0 如果空閒執行緒數<0,建立新的連線<br>
 * ####3.如果空閒執行緒數>0,則獲取當前空閒執行緒,存入在活動執行緒集合中 <br>
 * 3.釋放連線 <br>
 * ####3.1.1.判斷空閒執行緒數是否大於最大執行緒數 <br>
 * ####3.1.2.如果空閒執行緒數小於最大執行緒數,將該連線收回到 空閒 執行緒集合中<br>
 * ####3.1.3.刪除該連線對應的活動執行緒集合資料<br>
 * <br>
 * 
 * 
 * 作者: 每特教育-餘勝軍<br>
 * 聯絡方式:QQ644064779|WWW.itmayiedu.com<br>
 */
public class ConnectionPool implements IConnectionPool {

    // 空閒執行緒集合
    private List<Connection> freeConnection = new Vector<Connection>();
    // 活動執行緒集合
    private List<Connection> activeConnection = new Vector<Connection>();
    // 記錄執行緒總數
    private static int connCount = 0;
    private DbBean dbBean;

    public ConnectionPool(DbBean dbBean) {
        this.dbBean = dbBean;
        init();
    }

    public void init() {
        try {

            for (int i = 0; i < dbBean.getInitConnections(); i++) {
                Connection newConnection = newConnection();
                if (newConnection != null) {
                    // 新增到空閒執行緒中...
                    freeConnection.add(newConnection);
                }
            }

        } catch (Exception e) {

        }
    }

    // 建立新的Connection
    private Connection newConnection() {
        try {
            if (dbBean == null) {
                return null;
            }
            Class.forName(dbBean.getDriverName());
            Connection connection = DriverManager.getConnection(dbBean.getUrl(), dbBean.getUserName(),
                    dbBean.getPassword());
            connCount++;
            return connection;
        } catch (Exception e) {
            return null;
        }

    }

    public Connection getConnection() {
        // * ####1.判斷活動執行緒數是否大於最大執行緒 如果大於最大執行緒數,則進行等待...<br>
        Connection connection = null;
        try {

            if (connCount < dbBean.getMaxActiveConnections()) {
                // 還有活動執行緒可以使用
                // * ####2.判斷空閒執行緒數是否大於0 如果空閒執行緒數<0,建立新的連線<br>
                if (freeConnection.size() > 0) {
                    connection = freeConnection.remove(0);// 等於freeConnection.get(0);freeConnection.remove(0);
                } else {
                    // 建立新的連線
                    connection = newConnection();
                }

                boolean available = isAvailable(connection);
                if (available) {
                    activeConnection.add(connection);
                } else {
                    connCount--;// i--操作
                    connection = getConnection();// 遞迴呼叫getConnection方法
                }
            } else {
                // 大於最大執行緒數,進行等待,重新獲取連線
                wait(dbBean.getConnTimeOut());
                connection = getConnection();// 遞迴呼叫getConnection方法
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // * ####3.如果空閒執行緒數>0,則獲取當前空閒執行緒,存入在活動執行緒集合中 <br>
        return connection;
    }

    // 判斷連線是否可用
    public boolean isAvailable(Connection connection) {
        try {
            if (connection == null || connection.isClosed()) {
                return false;
            }

        } catch (Exception e) {
            // TODO: handle exception
        }
        return true;

    }

    public void releaseConnection(Connection connection) {
        try {
            if (connection == null) {
                return;
            }
            if (isAvailable(connection)) {
                // 判斷空閒執行緒數是否大於最大執行緒數
                if (freeConnection.size() < dbBean.getMaxConnections()) {
                    freeConnection.add(connection);
                } else {
                    // 空閒執行緒數已經滿了
                    connection.close();
                }
                activeConnection.remove(connection);
                connCount--;
                notifyAll();

            }

        } catch (Exception e) {

        }

    }

}

 

測試執行結果

public class Test001 {

    public static void main(String[] args) {

        DBThread dBThread = new DBThread();
        for (int i = 1; i <= 3; i++) {
            Thread thread = new Thread(dBThread, "使用者執行緒" + i);
            thread.start();
        }

    }

}

class DBThread implements Runnable {

    public void run() {
        for (int i = 0; i < 10; i++) {
            Connection connection = ConnectionPoolManager.getConnection();
            System.out.println(Thread.currentThread().getName() + ",connection:" + connection);
            ConnectionPoolManager.releaseConnection(connection);
        }
    }

}

 

相關文章