串連池是建立和管理一個串連的緩衝池的技術,這些串連準備好被任何需要它們的線程使用。
這種把串連“彙集”起來的技術基於這樣的一個事實:對於大多數應用程式,當它們正在處理通常需要數毫秒完成的事務時,僅需要能夠訪問JDBC 串連的 1 個線程。當不處理事務時,這個串連就會閑置。相反,串連池允許閑置的串連被其它需要的線程使用。
事實上,當一個線程需要用 JDBC 對一個 GBase 或其它資料庫操作時,它從池中請求一個串連。當這個線程使用完了這個串連,將它返回到串連池中,這樣這就可以被其它想使用它的線程使用。
當串連從池中“借出”,它被請求它的線程專有地使用。從編程的角度來看,這和使用者的線程每當需要一個 JDBC 串連的時候調用DriverManager.getConnection() 是一樣的,採用串連池技術,可通過使用新的或已有的串連結束線程。
串連池可以極大的改善使用者的 Java 應用程式的效能,同時減少全部資源的使用。串連池主要的優點有:
減少串連建立時間
雖然與其它資料庫相比 GBase 提供了較為快速串連功能,但是建立新的 JDBC 串連仍會招致網路和 JDBC 驅動的開銷。如果這類串連是“迴圈”使用的,使用該方式這些花銷就可避免。
簡化的編程模式
當使用串連池時,每一個單獨的線程能夠像建立了一個自己的 JDBC 串連一樣操作,允許使用者直接使用JDBC編程技術。
受控的資源使用
如果使用者不使用串連池,而是每當線程需要時建立一個新的串連,那麼使用者的應用程式的資源使用會產生非常大的浪費並且可能會導致高負載下的異常發生。
注意,每個連到 GBase 的串連在用戶端和伺服器端都有花銷(記憶體,CPU,環境切換等等)。每個串連均會對應用程式和 GBase 伺服器的可用資源帶來一定的限制。不管這些串連是否在做有用的工作,仍將使用這些資源中的相當一部分。
串連池能夠使效能最大化,同時還能將資源利用控制在一定的水平之下,如果超過該水平,應用程式將崩潰而不僅僅是變慢。
C3P0連線管理員
package cn.c3p0;import java.beans.PropertyVetoException;import java.sql.Connection;import java.sql.SQLException;import com.mchange.v2.c3p0.ComboPooledDataSource;public final class ConnectionManager { private static ConnectionManager instance; private static ComboPooledDataSource dataSource; private ConnectionManager() throws SQLException, PropertyVetoException { dataSource = new ComboPooledDataSource(); dataSource.setUser("hai"); dataSource.setPassword("1223"); dataSource.setJdbcUrl("jdbc:oracle:thin:@192.168.10.38:1521:ztsys"); dataSource.setDriverClass("oracle.jdbc.driver.OracleDriver"); dataSource.setInitialPoolSize(5); dataSource.setMinPoolSize(1); dataSource.setMaxPoolSize(10); dataSource.setMaxStatements(50); dataSource.setMaxIdleTime(60); } public static final ConnectionManager getInstance() { if (instance == null) { try { instance = new ConnectionManager(); } catch (Exception e) { e.printStackTrace(); } } return instance; } public synchronized final Connection getConnection() { Connection conn = null; try { conn = dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return conn; }}
測試例子:
package cn.c3p0;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import oracle.jdbc.pool.OracleDataSource;public class ConnectionDemo { public static void main(String[] args) throws SQLException { System.out.println("使用串連池................................"); for (int i = 0; i < 20; i++) { long beginTime = System.currentTimeMillis(); Connection conn = ConnectionManager.getInstance().getConnection(); try { PreparedStatement pstmt = conn.prepareStatement("select * from event t"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { // do nothing... } } catch (SQLException e) { e.printStackTrace(); } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } long endTime = System.currentTimeMillis(); System.out.println("第" + (i + 1) + "次執行花費時間為:" + (endTime - beginTime)); } System.out.println("不使用串連池................................"); for (int i = 0; i < 20; i++) { long beginTime = System.currentTimeMillis(); OracleDataSource ods = new OracleDataSource(); ods.setUser("hai"); ods.setPassword("1223"); ods.setURL("jdbc:oracle:thin:@192.168.10.38:1521:ztsys"); Connection conn = ods.getConnection(); try { PreparedStatement pstmt = conn.prepareStatement("select * from event t"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { // do nothing... } } catch (SQLException e) { e.printStackTrace(); } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } long endTime = System.currentTimeMillis(); System.out.println("第" + (i + 1) + "次執行花費時間為:" + (endTime - beginTime)); } }}
測試結果:
使用串連池................................
2011-8-23 14:23:10 com.mchange.v2.log.MLog <clinit>
資訊: MLog clients using java 1.4+ standard logging.
2011-8-23 14:23:10 com.mchange.v2.c3p0.C3P0Registry banner
資訊: Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
2011-8-23 14:23:10 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
資訊: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge3728h1w2au7f1c496sy|6e293a, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> oracle.jdbc.driver.OracleDriver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge3728h1w2au7f1c496sy|6e293a, idleConnectionTestPeriod -> 0, initialPoolSize -> 5, jdbcUrl -> jdbc:oracle:thin:@192.168.10.38:1521:ztsys, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 60, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 10, maxStatements -> 50, maxStatementsPerConnection -> 0, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
第1次執行花費時間為:1031
第2次執行花費時間為:172
第3次執行花費時間為:266
第4次執行花費時間為:156
第5次執行花費時間為:172
第6次執行花費時間為:156
第7次執行花費時間為:172
第8次執行花費時間為:141
第9次執行花費時間為:156
第10次執行花費時間為:172
第11次執行花費時間為:172
第12次執行花費時間為:156
第13次執行花費時間為:172
第14次執行花費時間為:172
第15次執行花費時間為:172
第16次執行花費時間為:171
第17次執行花費時間為:157
第18次執行花費時間為:156
第19次執行花費時間為:187
第20次執行花費時間為:157
不使用串連池................................
第1次執行花費時間為:187
第2次執行花費時間為:188
第3次執行花費時間為:187
第4次執行花費時間為:188
第5次執行花費時間為:187
第6次執行花費時間為:203
第7次執行花費時間為:188
第8次執行花費時間為:187
第9次執行花費時間為:188
第10次執行花費時間為:203
第11次執行花費時間為:203
第12次執行花費時間為:281
第13次執行花費時間為:188
第14次執行花費時間為:219
第15次執行花費時間為:203
第16次執行花費時間為:203
第17次執行花費時間為:187
第18次執行花費時間為:219
第19次執行花費時間為:219
第20次執行花費時間為:203