目前常用的數(shù)據(jù)源主要有c3p0、dbcp伶丐、proxool悼做、druid
Spring 推薦使用dbcp;
Hibernate 推薦使用c3p0和proxool
1哗魂、 DBCP:apache
DBCP(DataBase connection pool)數(shù)據(jù)庫連接池肛走。是apache上的一個 java連接池項目,也是 tomcat使用的連接池組件录别。單獨使用dbcp需要3個包:common-dbcp.jar,common-pool.jar,common-collections.jar由于建立數(shù)據(jù)庫連接是一個非常耗時耗資源的行為朽色,所以通過連接池預(yù)先同數(shù)據(jù)庫建立一些連接,放在內(nèi)存中组题,應(yīng)用程序需要建立數(shù)據(jù)庫連接時直接到連接池中申請一個就行葫男,用完后再放回去。dbcp沒有自動的去回收空閑連接的功能崔列。
2梢褐、 C3P0:
C3P0是一個開源的jdbc連接池,它實現(xiàn)了數(shù)據(jù)源和jndi綁定赵讯,支持jdbc3規(guī)范和jdbc2的標準擴展盈咳。c3p0是異步操作的,緩慢的jdbc操作通過幫助進程完成边翼。擴展這些操作可以有效的提升性能鱼响。目前使用它的開源項目有Hibernate,Spring等组底。c3p0有自動回收空閑連接功能热押。
3、 Proxool:Sourceforge
Proxool是一種Java數(shù)據(jù)庫連接池技術(shù)斤寇。是sourceforge下的一個開源項目,這個項目提供一個健壯桶癣、易用的連接池,最為關(guān)鍵的是這個連接池提供監(jiān)控的功能娘锁,方便易用牙寞,便于發(fā)現(xiàn)連接泄漏的情況。
綜合來說莫秆,穩(wěn)定性是dbcp>=c3p0>proxool
后來阿里巴巴的druid開源了间雀,可以是前無古人后無來者,最強沒有之一镊屎,十分穩(wěn)定惹挟,在大并發(fā)中表現(xiàn)十分好
基本原理
- pool.getConnection(),都是先從threadlocal里面拿的缝驳,如果threadlocal里面有连锯,則用归苍,保證線程里的多個dao操作,用的是同一個connection运怖,以保證事務(wù)拼弃。
- 如果新線程,則將新的connection放在threadlocal里摇展,再get給到線程吻氧。
重點代碼
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
// 獲得當前連接
public Connection getCurrentConnecton(){
// 默認線程里面取
Connection conn = threadLocal.get();
if(!isValid(conn)){
conn = getConnection();
}
return conn;
}
// 獲得連接
public synchronized Connection getConnection() {
Connection conn = null;
try {
// 判斷是否超過最大連接數(shù)限制
if(contActive < this.dbBean.getMaxActiveConnections()){
if (freeConnection.size() > 0) {
conn = freeConnection.get(0);
if (conn != null) {
threadLocal.set(conn);
}
freeConnection.remove(0);
} else {
conn = newConnection();
}
}else{
// 繼續(xù)獲得連接,直到從新獲得連接
wait(this.dbBean.getConnTimeOut());
conn = getConnection();
}
if (isValid(conn)) {
activeConnection.add(conn);
contActive ++;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return conn;
}
public synchronized void releaseConn(Connection conn) throws SQLException {
if (isValid(conn)&& !(freeConnection.size() > dbBean.getMaxConnections())) {
freeConnection.add(conn);
activeConnection.remove(conn);
contActive --;
threadLocal.remove();
// 喚醒所有正待等待的線程,去搶連接
notifyAll();
}
}
重理解此段話
什么是線程池,什么是ThreadLocal???
- 線程池,為避免不必要的創(chuàng)建,銷毀connection而存在的,其中包括活動,等待,最小等屬性,cop3,proxy連接池都可以配置這些玩意;
- 為什么要用ThreadLocal呢?這個和連接池無關(guān),我認為更多的是和程序本身相關(guān),為了更清楚的說明,舉個例子
servlet中獲取一個連接.首先,servlet是線程安全的嗎?
class MyServlet extends HttpServlet{
private Connection conn;
}
ok,遺憾的告訴你,這個conn并不是安全的,所有請求這個servlet的連接,使用的都是一個Connection,這個就是致命的了.多個人使用同一個連接,算上延遲啥的,天知道數(shù)據(jù)會成什么樣.
因此我們要保證Connection對每個請求都是唯一的.這個時候就可以用到ThreadLocal了,保證每個線程都有自己的連接.
改為 private ThreadLocal<Connection> ct = new ThreadLocal<Connnection>();
然后從連接池獲取Connection,set到ct中,再get就行了,至于得到的是哪個Connection就是連接池的問題了,你也管不到咏连。