【java】數據庫連接池的自定義實現

數據庫連接池的使用

傳統方式
當有多個線程,每個線程都需要連接數據庫執行SQL語句的話,那麼每個線程都會創建一個連接,並且在使用完畢後,關閉連接。這一點自己在平時寫程序的時候都是自己創建connection對象,然後用完就關閉。這就很耗時和浪費資源

創建連接和關閉連接的過程也是比較消耗時間的,當多線程併發的時候,系統就會變得很卡頓。

同時,一個數據庫同時支持的連接總數也是有限的,如果多線程併發量很大,那麼數據庫連接的總數就會被消耗光,後續線程發起的數據庫連接就會失敗。

改進方式:
與傳統方式不同,連接池在使用之前,就會創建好一定數量的連接。
如果有任何線程需要使用連接,那麼就從連接池裏面借用,而不是自己重新創建.
使用完畢後,又把這個連接歸還給連接池供下一次或者其他線程使用。
倘若發生多線程併發情況,連接池裏的連接被借用光了,那麼其他線程就會臨時等待,直到有連接被歸還回來,再繼續使用。
整個過程,這些連接都不會被關閉,而是不斷的被循環使用,從而節約了啓動和關閉連接的時間。

還記得上安卓課時候,張吳波老師說連接池就像一個魚缸一樣,要吃魚的時候就拿出一條來,吃完了就放回去,把我們都逗笑了。。。。23333

代碼

自定義數據庫連接池的實現代碼:就是借用操作系統中的生產者-消費者模型,來維護一個緩衝區。這次進行併發控制。

package dbpool;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;

/**
 * describe:
 *
 * @author yanzhizheng
 * @date 2019//26
 * 按照how2j上實現的線程池
 */

public class ConnectPool {

    private LinkedList<Connection> pool = new LinkedList<Connection>();
    int size;

    public ConnectPool(int size) {
        this.size = size;
        init(); //調用init方法初始化隊列
    }

    public void init(){
        //加載驅動源
        try {
            Class.forName("com.mysql.jdbc.Driver");
            for (int i = 0; i < size; i++) {
                Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test",
                        "root","mysql");
                pool.addLast(conn);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
        }
    }
    public synchronized Connection getConnection(){
        while (pool.isEmpty()) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return  pool.removeFirst();
    }

    public  synchronized  void releaseConnction(Connection conn) {
        pool.addLast(conn);
        this.notifyAll();   //喚醒等待的進程
    }

    public static void main(String[] args) {
        ConnectPool pool = new ConnectPool(3); //初始化10個連接對象放到池子中
        for (int i = 0; i < 10; i++) {
            new WorkThread("work thread" + i, pool).start();
        }
    }
}

class  WorkThread extends  Thread {
    private  ConnectPool pool;
    public WorkThread(String name, ConnectPool pool) {
        super(name);
        this.pool = pool;
    }
    public void run() {
        Connection c = pool.getConnection();//獲取連接池中的連接
        System.out.println(this.getName() + ":\t 獲取連接" + "連接的對象的值" + c.toString());
        try(Statement psmt = c.createStatement()) {
            Thread.sleep(10000);    //睡眠10ms容易有效果
            //執行sql語句
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        pool.releaseConnction(c);
    }
}

代碼結果

可以看到後面的線程都是使用那三個連接對象。
file1

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