diff --git a/src/test/java/com/alibaba/druid/bvt/pool/TestIdle3_Concurrent_Starvation.java b/src/test/java/com/alibaba/druid/bvt/pool/TestIdle3_Concurrent_Starvation.java new file mode 100644 index 0000000000..32d47a4ece --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/TestIdle3_Concurrent_Starvation.java @@ -0,0 +1,138 @@ +package com.alibaba.druid.bvt.pool; + +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 TestIdle3_Concurrent_Starvation extends TestCase { + + private MockDriver driver; + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + driver = new MockDriver(); + + 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(300 * 1000); // 300 / 10 + dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10 + dataSource.setTestWhileIdle(true); + dataSource.setTestOnBorrow(false); + dataSource.setValidationQuery("SELECT 1"); + dataSource.setFilters("stat"); + } + + public void test_idle2() throws Exception { + + 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(1, driver.getConnections().size()); + Assert.assertEquals(1, dataSource.getCreateCount()); + Assert.assertEquals(0, dataSource.getActiveCount()); + } + + for (int i = 0; i < 1; ++i) { + final int threadCount = 10; + concurrent(threadCount); + } + + // 连续打开关闭单个连接 + 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 int threadCount) throws Exception { + Thread[] threads = new Thread[threadCount]; + final CountDownLatch startLatch = new CountDownLatch(1); + final CountDownLatch endLatch = new CountDownLatch(threadCount); + + final AtomicInteger pass = new AtomicInteger(); + + final CyclicBarrier closedBarrier = new CyclicBarrier(threadCount, new Runnable() { + public void run() { + Assert.assertEquals(threadCount, dataSource.getPoolingCount()); + dataSource.shrink(false); + Assert.assertEquals(0, dataSource.getActiveCount()); + Assert.assertEquals(dataSource.getMinIdle(), dataSource.getPoolingCount()); + if (pass.getAndIncrement() % 10000 == 0) { + System.out.println("pass : " + pass.get()); + } + } + }); + final CyclicBarrier closeBarrier = new CyclicBarrier(threadCount, new Runnable() { + public void run() { + Assert.assertEquals(threadCount, dataSource.getActiveCount()); + } + }); + + for (int i = 0; i < threadCount; ++i) { + threads[i] = new Thread("thread-" + i) { + + public void run() { + try { + startLatch.await(); + for (int i = 0; i < 1000 * 1000; ++i) { + + Connection conn = dataSource.getConnection(); + closeBarrier.await(); + + conn.close(); + closedBarrier.await(); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + endLatch.countDown(); + } + } + }; + } + + startLatch.countDown(); + for (int i = 0; i < threadCount; ++i) { + threads[i].start(); + } + + endLatch.await(); + + // int max = count > dataSource.getMaxActive() ? dataSource.getMaxActive() : count; + // Assert.assertEquals(max, driver.getConnections().size()); + } +}