mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
修正connection.close的并发问题
git-svn-id: http://code.alibabatech.com/svn/druid/trunk@326 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
@@ -271,6 +271,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
*/
|
||||
protected void recycle(PoolableConnection pooledConnection) throws SQLException {
|
||||
final Connection conn = pooledConnection.getConnection();
|
||||
ConnectionHolder holder = pooledConnection.getConnectionHolder();
|
||||
|
||||
assert holder != null;
|
||||
|
||||
try {
|
||||
if (activeConnectionTraceEnable) {
|
||||
activeConnections.remove(pooledConnection);
|
||||
@@ -280,6 +284,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
if (conn == null || conn.isClosed()) {
|
||||
lock.lock();
|
||||
try {
|
||||
holder.reset();
|
||||
decrementActiveCount();
|
||||
closeCount++;
|
||||
} finally {
|
||||
@@ -306,6 +311,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
if (count >= maxIdle) {
|
||||
lock.lock();
|
||||
try {
|
||||
holder.reset();
|
||||
conn.close();
|
||||
decrementActiveCount();
|
||||
} finally {
|
||||
@@ -328,7 +334,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
closeCount++;
|
||||
|
||||
// 第六步,加入队列中(putLast)
|
||||
putLast(pooledConnection.getConnectionHolder());
|
||||
holder.reset();
|
||||
putLast(holder);
|
||||
recycleCount++;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
|
||||
@@ -57,7 +57,7 @@ public class PoolableConnection implements PooledConnection, Connection {
|
||||
protected SQLException handleException(Throwable t) throws SQLException {
|
||||
final ConnectionHolder holder = this.holder;
|
||||
|
||||
//
|
||||
//
|
||||
if (holder != null) {
|
||||
DruidAbstractDataSource dataSource = holder.getDataSource();
|
||||
if (dataSource != null) {
|
||||
@@ -124,7 +124,6 @@ public class PoolableConnection implements PooledConnection, Connection {
|
||||
}
|
||||
|
||||
holder.getDataSource().recycle(this);
|
||||
holder.reset();
|
||||
holder = null;
|
||||
conn = null;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ public class PoolableStatement extends PoolableWrapper implements Statement {
|
||||
private final Statement stmt;
|
||||
protected PoolableConnection conn;
|
||||
protected final List<ResultSet> resultSetTrace = new ArrayList<ResultSet>();
|
||||
protected boolean closed = false;
|
||||
|
||||
public PoolableStatement(PoolableConnection conn, Statement stmt){
|
||||
this.conn = conn;
|
||||
@@ -49,6 +50,10 @@ public class PoolableStatement extends PoolableWrapper implements Statement {
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
public Statement getStatement() {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
protected void clearResultSet() {
|
||||
for (ResultSet rs : resultSetTrace) {
|
||||
try {
|
||||
@@ -90,6 +95,7 @@ public class PoolableStatement extends PoolableWrapper implements Statement {
|
||||
clearResultSet();
|
||||
|
||||
stmt.close();
|
||||
this.closed = true;
|
||||
|
||||
conn.getConnectionHolder().removeTrace(this);
|
||||
}
|
||||
@@ -409,6 +415,10 @@ public class PoolableStatement extends PoolableWrapper implements Statement {
|
||||
|
||||
@Override
|
||||
public final boolean isClosed() throws SQLException {
|
||||
if (this.closed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
return stmt.isClosed();
|
||||
} catch (Throwable t) {
|
||||
|
||||
@@ -19,7 +19,7 @@ public class StatFilterTest extends TestCase {
|
||||
public void setUp() throws Exception {
|
||||
JdbcStatManager.getInstance().reset();
|
||||
}
|
||||
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
JdbcStatManager.getInstance().reset();
|
||||
}
|
||||
@@ -27,7 +27,7 @@ public class StatFilterTest extends TestCase {
|
||||
public void test_stat() throws Exception {
|
||||
String url = "jdbc:wrap-jdbc:filters=default:jdbc:mock:xx";
|
||||
Connection conn = DriverManager.getConnection(url);
|
||||
|
||||
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery("SELECT 1");
|
||||
while (rs.next()) {
|
||||
@@ -35,18 +35,22 @@ public class StatFilterTest extends TestCase {
|
||||
}
|
||||
rs.close();
|
||||
stmt.close();
|
||||
|
||||
|
||||
conn.close();
|
||||
|
||||
|
||||
TabularData sqlList = JdbcStatManager.getInstance().getSqlList();
|
||||
Assert.assertEquals(true, sqlList.size() > 0);
|
||||
|
||||
|
||||
int count = 0;
|
||||
for (Object item : sqlList.values()) {
|
||||
CompositeData row = (CompositeData) item;
|
||||
Assert.assertEquals(url, (String) row.get("URL"));
|
||||
if (url.equals((String) row.get("URL"))) {
|
||||
count++;
|
||||
}
|
||||
Assert.assertEquals(0, row.get("Count_50000_more"));
|
||||
}
|
||||
|
||||
Assert.assertEquals(true, count > 0);
|
||||
|
||||
System.out.println(JSON.toJSONString(sqlList));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.alibaba.druid.pool.benckmark;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.commons.dbcp.BasicDataSource;
|
||||
|
||||
import com.alibaba.druid.TestUtil;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
|
||||
public class Oracle_Case3 extends TestCase {
|
||||
|
||||
private String jdbcUrl;
|
||||
private String user;
|
||||
private String password;
|
||||
private String driverClass;
|
||||
private int maxIdle = 40;
|
||||
private int maxActive = 50;
|
||||
private int maxWait = 5000;
|
||||
private String validationQuery = "SELECT 1 FROM DUAL";
|
||||
private int threadCount = 14;
|
||||
private int loopCount = 3;
|
||||
final int LOOP_COUNT = 100 * 1;
|
||||
private boolean testOnBorrow = true;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
jdbcUrl = "jdbc:oracle:thin:@10.20.149.85:1521:ocnauto";
|
||||
user = "alibaba";
|
||||
password = "ccbuauto";
|
||||
driverClass = "oracle.jdbc.driver.OracleDriver";
|
||||
}
|
||||
|
||||
public void test_0() throws Exception {
|
||||
DruidDataSource dataSource = new DruidDataSource();
|
||||
|
||||
dataSource.setMaxActive(maxActive);
|
||||
dataSource.setMaxIdle(maxIdle);
|
||||
dataSource.setMaxWait(maxWait);
|
||||
dataSource.setPoolPreparedStatements(true);
|
||||
dataSource.setDriverClassName(driverClass);
|
||||
dataSource.setUrl(jdbcUrl);
|
||||
dataSource.setPoolPreparedStatements(true);
|
||||
dataSource.setUsername(user);
|
||||
dataSource.setPassword(password);
|
||||
dataSource.setValidationQuery(validationQuery);
|
||||
dataSource.setTestOnBorrow(testOnBorrow);
|
||||
|
||||
for (int i = 0; i < loopCount; ++i) {
|
||||
p0(dataSource, "druid", threadCount);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
public void test_1() throws Exception {
|
||||
final BasicDataSource dataSource = new BasicDataSource();
|
||||
|
||||
dataSource.setMaxActive(maxActive);
|
||||
dataSource.setMaxIdle(maxIdle);
|
||||
dataSource.setMaxWait(maxWait);
|
||||
dataSource.setPoolPreparedStatements(true);
|
||||
dataSource.setDriverClassName(driverClass);
|
||||
dataSource.setUrl(jdbcUrl);
|
||||
dataSource.setPoolPreparedStatements(true);
|
||||
dataSource.setUsername(user);
|
||||
dataSource.setPassword(password);
|
||||
dataSource.setValidationQuery(validationQuery);
|
||||
dataSource.setTestOnBorrow(testOnBorrow);
|
||||
|
||||
for (int i = 0; i < loopCount; ++i) {
|
||||
p0(dataSource, "dbcp", threadCount);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {
|
||||
|
||||
final CountDownLatch startLatch = new CountDownLatch(1);
|
||||
final CountDownLatch endLatch = new CountDownLatch(1);
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
Thread thread = new Thread() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
startLatch.await();
|
||||
|
||||
for (int i = 0; i < LOOP_COUNT; ++i) {
|
||||
Connection conn = dataSource.getConnection();
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery("SELECT 1 FROM DUAL");
|
||||
rs.next();
|
||||
rs.close();
|
||||
stmt.close();
|
||||
conn.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
endLatch.countDown();
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
}
|
||||
long startMillis = System.currentTimeMillis();
|
||||
long startYGC = TestUtil.getYoungGC();
|
||||
long startFullGC = TestUtil.getFullGC();
|
||||
startLatch.countDown();
|
||||
endLatch.await();
|
||||
|
||||
long millis = System.currentTimeMillis() - startMillis;
|
||||
long ygc = TestUtil.getYoungGC() - startYGC;
|
||||
long fullGC = TestUtil.getFullGC() - startFullGC;
|
||||
|
||||
System.out.println("thread " + threadCount + " " + name + " millis : " + NumberFormat.getInstance().format(millis) + ", YGC " + ygc + " FGC " + fullGC);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user