diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java index ca52733427..9d744e869a 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java @@ -30,8 +30,6 @@ public interface DruidAbstractDataSourceMBean { int getActiveCount(); - long getIdleCheckCount(); - long getCreateCount(); long getDestroyCount(); diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 9cd198aea4..dd0a3ff7df 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -82,7 +82,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private long recycleCount = 0; private long createConnectionCount = 0L; private long destroyCount = 0; - private long idleCheckCount = 0; // store private ConnectionHolder[] connections; @@ -630,10 +629,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return activeCount; } - public long getIdleCheckCount() { - return idleCheckCount; - } - public class CreateConnectionThread extends Thread { public CreateConnectionThread(String name){ diff --git a/src/test/java/com/alibaba/druid/TestIdel3.java b/src/test/java/com/alibaba/druid/TestIdel3.java new file mode 100644 index 0000000000..58fc9bd5a8 --- /dev/null +++ b/src/test/java/com/alibaba/druid/TestIdel3.java @@ -0,0 +1,140 @@ +package com.alibaba.druid; + +import java.lang.management.ManagementFactory; +import java.sql.Connection; +import java.util.concurrent.CountDownLatch; + +import javax.management.ObjectName; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.mock.MockDriver; +import com.alibaba.druid.pool.DruidDataSource; + +public class TestIdel3 extends TestCase { + + public void test_idle2() throws Exception { + MockDriver driver = new MockDriver(); + + final DruidDataSource dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setDriver(driver); + dataSource.setInitialSize(1); + dataSource.setMaxActive(14); + dataSource.setMaxIdle(14); + dataSource.setMinIdle(1); + dataSource.setMinEvictableIdleTimeMillis(3 * 100); // 300 / 10 + dataSource.setTimeBetweenEvictionRunsMillis(18 * 10); // 180 / 10 + dataSource.setTestWhileIdle(true); + dataSource.setTestOnBorrow(false); + dataSource.setValidationQuery("SELECT 1"); + dataSource.setFilters("stat"); + + ManagementFactory.getPlatformMBeanServer().registerMBean(dataSource, + new ObjectName("com.alibaba:type=DataSource")); + + // 第一次创建连接 + { + Assert.assertEquals(0, dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + + Connection conn = dataSource.getConnection(); + + Assert.assertEquals(dataSource.getInitialSize(), dataSource.getCreateCount()); + Assert.assertEquals(dataSource.getInitialSize(), driver.getConnections().size()); + Assert.assertEquals(1, dataSource.getActiveCount()); + + conn.close(); + Assert.assertEquals(0, dataSource.getDestroyCount()); + Assert.assertEquals(2, driver.getConnections().size()); + Assert.assertEquals(2, dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + } + + { + // 并发创建14个 + int count = 14; + Connection[] connections = new Connection[count]; + for (int i = 0; i < count; ++i) { + connections[i] = dataSource.getConnection(); + Assert.assertEquals(i + 1, dataSource.getActiveCount()); + } + + Assert.assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount()); + Assert.assertEquals(count, driver.getConnections().size()); + + // 全部关闭 + for (int i = 0; i < count; ++i) { + connections[i].close(); + Assert.assertEquals(count - i - 1, dataSource.getActiveCount()); + } + + Assert.assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + Assert.assertEquals(14, driver.getConnections().size()); + } + + concurrent(dataSource, 100, 1000); + concurrent(dataSource, 1, 1000 * 1000); + Thread.sleep(1000 * 10); + concurrent(dataSource, 1, 1000 * 1000); + Thread.sleep(1000 * 10); + concurrent(dataSource, 1000, 1000 * 1000); + + Assert.assertEquals(driver.getConnections().size(), dataSource.getPoolingCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + + // 连续打开关闭单个连接 + for (int i = 0; i < 1000; ++i) { + Assert.assertEquals(0, dataSource.getActiveCount()); + Connection conn = dataSource.getConnection(); + + Assert.assertEquals(1, dataSource.getActiveCount()); + + Thread.sleep(10); + conn.close(); + } + //Assert.assertEquals(2, dataSource.getPoolingCount()); + + Thread.sleep(1000 * 100); + dataSource.close(); + + + } + + private void concurrent(final DruidDataSource dataSource, int threadCount, final int loopCount) throws InterruptedException { + + final CountDownLatch startLatch = new CountDownLatch(1); + final CountDownLatch endLatch = new CountDownLatch(threadCount); + Thread[] threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; ++i) { + threads[i] = new Thread("thread-" + i) { + + public void run() { + try { + startLatch.await(); + for (int i = 0; i < loopCount; ++i) { + Connection conn = null; + + conn = dataSource.getConnection(); + conn.close(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + endLatch.countDown(); + } + } + }; + } + + for (int i = 0; i < threadCount; ++i) { + threads[i].start(); + } + startLatch.countDown(); + System.out.println("concurrent start..."); + endLatch.await(); + System.out.println("concurrent end"); + } +} diff --git a/src/test/java/com/alibaba/druid/TestIdel3_Concurrent.java b/src/test/java/com/alibaba/druid/TestIdel3_Concurrent.java new file mode 100644 index 0000000000..7761b34ad1 --- /dev/null +++ b/src/test/java/com/alibaba/druid/TestIdel3_Concurrent.java @@ -0,0 +1,107 @@ +package com.alibaba.druid; + +import java.lang.management.ManagementFactory; +import java.sql.Connection; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.management.ObjectName; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.mock.MockDriver; +import com.alibaba.druid.pool.DruidDataSource; + +public class TestIdel3_Concurrent extends TestCase { + + public void test_idle2() throws Exception { + MockDriver driver = new MockDriver(); + + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setDriver(driver); + dataSource.setInitialSize(1); + dataSource.setMaxActive(2); + dataSource.setMaxIdle(2); + dataSource.setMinIdle(1); + dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10 + dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10 + dataSource.setTestWhileIdle(true); + dataSource.setTestOnBorrow(false); + dataSource.setValidationQuery("SELECT 1"); + dataSource.setFilters("stat"); + + ManagementFactory.getPlatformMBeanServer().registerMBean(dataSource, new ObjectName("com.alibaba:type=DataSource")); + + // 第一次创建连接 + { + Assert.assertEquals(0, dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + + Connection conn = dataSource.getConnection(); + + Assert.assertEquals(dataSource.getInitialSize(), dataSource.getCreateCount()); + Assert.assertEquals(dataSource.getInitialSize(), driver.getConnections().size()); + Assert.assertEquals(1, dataSource.getActiveCount()); + + conn.close(); + Assert.assertEquals(0, dataSource.getDestroyCount()); + Assert.assertEquals(2, driver.getConnections().size()); + Assert.assertEquals(2, dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + } + + { + // 并发创建14个 + concurrent(driver, dataSource, 3); + } + + // 连续打开关闭单个连接 + for (int i = 0; i < 1000; ++i) { + Assert.assertEquals(0, dataSource.getActiveCount()); + Connection conn = dataSource.getConnection(); + + Assert.assertEquals(1, dataSource.getActiveCount()); + conn.close(); + } + Assert.assertEquals(2, dataSource.getPoolingCount()); + + dataSource.close(); + } + + private void concurrent(final MockDriver driver, final DruidDataSource dataSource, final int count) throws Exception { + final int LOOP_COUNT = 1000; + Thread[] threads = new Thread[count]; + final CountDownLatch endLatch = new CountDownLatch(count); + for (int i = 0; i < count; ++i) { + threads[i] = new Thread("thread-" + i) { + public void run() { + try { + for (int i = 0; i < LOOP_COUNT; ++i) { + Connection conn = dataSource.getConnection(); + conn.isClosed(); + conn.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + endLatch.countDown(); + } + } + }; + } + + for (int i = 0; i < count; ++i) { + threads[i].start(); + } + + endLatch.await(); + System.out.println("concurrent end"); + + int max = count > dataSource.getMaxActive() ? dataSource.getMaxActive() : count; + Assert.assertEquals(max, driver.getConnections().size()); + + } +} diff --git a/src/test/java/com/alibaba/druid/TestLockCount.java b/src/test/java/com/alibaba/druid/TestLockCount.java new file mode 100644 index 0000000000..9a26e7ac41 --- /dev/null +++ b/src/test/java/com/alibaba/druid/TestLockCount.java @@ -0,0 +1,214 @@ +package com.alibaba.druid; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class TestLockCount extends TestCase { + + public void test_current() throws Exception { + DataSource dataSource = new DataSource(); + + final int threadCount = 10; + final int loopCount = 1000 * 1000 * 1000; + concurrent(dataSource, threadCount, loopCount); + long result = (long) threadCount * ((long) loopCount); + + Assert.assertEquals(result, dataSource.getCount()); + Assert.assertEquals(result, dataSource.getC0()); + Assert.assertEquals(result, dataSource.getC1()); + Assert.assertEquals(result, dataSource.getC2()); + Assert.assertEquals(result, dataSource.getC3()); + Assert.assertEquals(result, dataSource.getC4()); + Assert.assertEquals(result, dataSource.getC5()); + Assert.assertEquals(result, dataSource.getC6()); + Assert.assertEquals(result, dataSource.getC7()); + Assert.assertEquals(result, dataSource.getC8()); + Assert.assertEquals(result, dataSource.getC9()); + + Assert.assertEquals(result, dataSource.getC10()); + Assert.assertEquals(result, dataSource.getC11()); + Assert.assertEquals(result, dataSource.getC12()); + Assert.assertEquals(result, dataSource.getC13()); + Assert.assertEquals(result, dataSource.getC14()); + Assert.assertEquals(result, dataSource.getC15()); + Assert.assertEquals(result, dataSource.getC16()); + Assert.assertEquals(result, dataSource.getC17()); + Assert.assertEquals(result, dataSource.getC18()); + Assert.assertEquals(result, dataSource.getC19()); + } + + private void concurrent(final DataSource dataSource, int threadCount, final int loopCount) + throws InterruptedException { + + final CountDownLatch startLatch = new CountDownLatch(1); + final CountDownLatch endLatch = new CountDownLatch(threadCount); + Thread[] threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; ++i) { + threads[i] = new Thread("thread-" + i) { + + public void run() { + try { + startLatch.await(); + for (int i = 0; i < loopCount; ++i) { + dataSource.increment(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + endLatch.countDown(); + } + } + }; + } + + for (int i = 0; i < threadCount; ++i) { + threads[i].start(); + } + startLatch.countDown(); + System.out.println("concurrent start..."); + endLatch.await(); + System.out.println("concurrent end"); + } + + private static class DataSource { + + private long c0; + private long c1; + private long c2; + private long c3; + private long c4; + private long c5; + private long c6; + private long c7; + private long c8; + private long c9; + private long c10; + private long c11; + private long c12; + private long c13; + private long c14; + private long c15; + private long c16; + private long c17; + private long c18; + private long c19; + private final Lock lock = new ReentrantLock(); + + public long getCount() { + return c1; + } + + public long getC0() { + return c0; + } + + public long getC1() { + return c1; + } + + public long getC2() { + return c2; + } + + public long getC3() { + return c3; + } + + public long getC4() { + return c4; + } + + public long getC5() { + return c5; + } + + public long getC6() { + return c6; + } + + public long getC7() { + return c7; + } + + public long getC8() { + return c8; + } + + public long getC9() { + return c9; + } + + public long getC10() { + return c10; + } + + public long getC11() { + return c11; + } + + public long getC12() { + return c12; + } + + public long getC13() { + return c13; + } + + public long getC14() { + return c14; + } + + public long getC15() { + return c15; + } + + public long getC16() { + return c16; + } + + public long getC17() { + return c17; + } + + public long getC18() { + return c18; + } + + public long getC19() { + return c19; + } + + public void increment() { + lock.lock(); + try { + c0++; + c1++; + c2++; + c3++; + c4++; + c5++; + c6++; + c7++; + c8++; + c9++; + c10++; + c11++; + c12++; + c13++; + c14++; + c15++; + c16++; + c17++; + c18++; + c19++; + } finally { + lock.unlock(); + } + } + + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/pool/TestIdel3.java b/src/test/java/com/alibaba/druid/bvt/pool/TestIdel3.java new file mode 100644 index 0000000000..cf62ba0489 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/TestIdel3.java @@ -0,0 +1,91 @@ +package com.alibaba.druid.bvt.pool; + +import java.lang.management.ManagementFactory; +import java.sql.Connection; + +import javax.management.ObjectName; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.mock.MockDriver; +import com.alibaba.druid.pool.DruidDataSource; + +public class TestIdel3 extends TestCase { + + public void test_idle2() throws Exception { + MockDriver driver = new MockDriver(); + + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setDriver(driver); + dataSource.setInitialSize(1); + dataSource.setMaxActive(14); + dataSource.setMaxIdle(14); + dataSource.setMinIdle(1); + dataSource.setMinEvictableIdleTimeMillis(30 * 100); // 300 / 10 + dataSource.setTimeBetweenEvictionRunsMillis(18 * 100); // 180 / 10 + dataSource.setTestWhileIdle(true); + dataSource.setTestOnBorrow(false); + dataSource.setValidationQuery("SELECT 1"); + dataSource.setFilters("stat"); + + ManagementFactory.getPlatformMBeanServer().registerMBean(dataSource, new ObjectName("com.alibaba:type=DataSource,name=mysql")); + ManagementFactory.getPlatformMBeanServer().registerMBean(dataSource, new ObjectName("com.alibaba:type=DataSource,name=oracle")); + + // 第一次创建连接 + { + Assert.assertEquals(0, dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + + Connection conn = dataSource.getConnection(); + + Assert.assertEquals(dataSource.getInitialSize(), dataSource.getCreateCount()); + Assert.assertEquals(dataSource.getInitialSize(), driver.getConnections().size()); + Assert.assertEquals(1, dataSource.getActiveCount()); + + conn.close(); + Assert.assertEquals(0, dataSource.getDestroyCount()); + Assert.assertEquals(2, driver.getConnections().size()); + Assert.assertEquals(2, dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + } + + { + // 并发创建14个 + int count = 14; + Connection[] connections = new Connection[count]; + for (int i = 0; i < count; ++i) { + connections[i] = dataSource.getConnection(); + Assert.assertEquals(i + 1, dataSource.getActiveCount()); + } + + Assert.assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount()); + Assert.assertEquals(count, driver.getConnections().size()); + + // 全部关闭 + for (int i = 0; i < count; ++i) { + connections[i].close(); + Assert.assertEquals(count - i - 1, dataSource.getActiveCount()); + } + + Assert.assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + Assert.assertEquals(14, driver.getConnections().size()); + } + + // 连续打开关闭单个连接 + for (int i = 0; i < 1000; ++i) { + Assert.assertEquals(0, dataSource.getActiveCount()); + Connection conn = dataSource.getConnection(); + + Assert.assertEquals(1, dataSource.getActiveCount()); + + Thread.sleep(10); + conn.close(); + } + Assert.assertEquals(true, dataSource.getPoolingCount() == 2 || dataSource.getPoolingCount() == 1); + + dataSource.close(); + } +} diff --git a/src/test/java/com/alibaba/druid/pool/ui/DruidDataSourceUIManager.java b/src/test/java/com/alibaba/druid/pool/ui/DruidDataSourceUIManager.java index 61067370a8..ac7d42d982 100644 --- a/src/test/java/com/alibaba/druid/pool/ui/DruidDataSourceUIManager.java +++ b/src/test/java/com/alibaba/druid/pool/ui/DruidDataSourceUIManager.java @@ -18,9 +18,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanRegistrationException; -import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.swing.JButton; import javax.swing.JFrame; @@ -548,7 +545,6 @@ public class DruidDataSourceUIManager extends JFrame { statusPanel.set("RecycleCount", dataSource.getRecycleCount()); statusPanel.set("ActiveCount", dataSource.getActiveCount()); statusPanel.set("PoolingCount", dataSource.getPoolingCount()); - statusPanel.set("IdleCheckCount", dataSource.getIdleCheckCount()); statusPanel.set("UI_GettingCount", connectingCount.get()); statusPanel.set("UI_GetCount", connectCount.get()); statusPanel.set("UI_ReleaseCount", closeCount.get());