資料庫連接池
與執行緒池類似的,資料庫也有一個資料庫連接池, 不過他們的實作思路是不一樣的,
本章節講解了自定義資料庫連接池類:ConnectionPool,雖然不是很完善和健壯,但是足以幫助大家理解ConnectionPool的基本原理,
步驟 1 : 資料庫連接池原理-傳統方式
當有多個執行緒,每個執行緒都需要連接資料庫執行SQL陳述句的話,那么每個執行緒都會創建一個連接,并且在使用完畢后,關閉連接,
創建連接和關閉連接的程序也是比較消耗時間的,當多執行緒并發的時候,系統就會變得很卡頓,
同時,一個資料庫同時支持的連接總數也是有限的,如果多執行緒并發量很大,那么資料庫連接的總數就會被消耗光,后續執行緒發起的資料庫連接就會失敗,

步驟 2 : 資料庫連接池原理-使用池
與傳統方式不同,連接池在使用之前,就會創建好一定數量的連接,
如果有任何執行緒需要使用連接,那么就從連接池里面借用,而不是自己重新創建.
使用完畢后,又把這個連接歸還給連接池供下一次或者其他執行緒使用,
倘若發生多執行緒并發情況,連接池里的連接被借用光了,那么其他執行緒就會臨時等待,直到有連接被歸還回來,再繼續使用,
整個程序,這些連接都不會被關閉,而是不斷的被回圈使用,從而節約了啟動和關閉連接的時間,

步驟 3 : ConnectionPool構造方法和初始化
-
ConnectionPool() 構造方法約定了這個連接池一共有多少連接
-
在init() 初始化方法中,創建了size條連接, 注意,這里不能使用try-with-resource這種自動關閉連接的方式,因為連接恰恰需要保持不關閉狀態,供后續回圈使用
-
getConnection, 判斷是否為空,如果是空的就wait等待,否則就借用一條連接出去
-
returnConnection, 在使用完畢后,歸還這個連接到連接池,并且在歸還完畢后,呼叫notifyAll,通知那些等待的執行緒,有新的連接可以借用了,
注:連接池設計用到了多執行緒的wait和notifyAll
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class ConnectionPool {
List<Connection> cs = new ArrayList<Connection>();
int size;
public ConnectionPool(int size) {
this.size = size;
init();
}
public void init() {
//這里恰恰不能使用try-with-resource的方式,因為這些連接都需要是"活"的,不要被自動關閉了
try {
Class.forName("com.mysql.jdbc.Driver");
for (int i = 0; i < size; i++) {
Connection c = DriverManager
.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root", "admin");
cs.add(c);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized Connection getConnection() {
while (cs.isEmpty()) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Connection c = cs.remove(0);
return c;
}
public synchronized void returnConnection(Connection c) {
cs.add(c);
this.notifyAll();
}
}
步驟 4 : 測驗類
首先初始化一個有3條連接的資料庫連接池
然后創建100個執行緒,每個執行緒都會從連接池中借用連接,并且在借用之后,歸還連接, 拿到連接之后,執行一個耗時1秒的SQL陳述句,
運行程式,就可以觀察到如圖所示的效果

package jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import jdbc.ConnectionPool;
public class TestConnectionPool {
public static void main(String[] args) {
ConnectionPool cp = new ConnectionPool(3);
for (int i = 0; i < 100; i++) {
new WorkingThread("working thread" + i, cp).start();
}
}
}
class WorkingThread extends Thread {
private ConnectionPool cp;
public WorkingThread(String name, ConnectionPool cp) {
super(name);
this.cp = cp;
}
public void run() {
Connection c = cp.getConnection();
System.out.println(this.getName()+ ":\t 獲取了一根連接,并開始作業" );
try (Statement st = c.createStatement()){
//模擬時耗1秒的資料庫SQL陳述句
Thread.sleep(1000);
st.execute("select * from hero");
} catch (SQLException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cp.returnConnection(c);
}
}
更多內容,點擊了解: JDBC 資料庫連接池
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/115583.html
標籤:Java
上一篇:使用awk分析JVM GC日志
