From 90b14ec70be525bd88f4f224a7b3aa84c8601bc8 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 10 Sep 2011 12:58:02 +0000 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=B7=B1=E7=BB=B4=E6=8A=A4notEmptyWai?= =?UTF-8?q?tThreadCount=E8=AE=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://code.alibabatech.com/svn/druid/trunk@713 b9813039-fb51-4c41-a8b9-e21c2acb5095 --- .../alibaba/druid/pool/DruidDataSource.java | 56 ++++++++++--------- .../benckmark/TestAtomicPerformance.java | 45 +++++++++++++++ .../pool/TestIdle3_Concurrent_Starvation.java | 2 +- 3 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/benckmark/TestAtomicPerformance.java diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 3c3d1a8394..6449698635 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -59,41 +59,42 @@ import com.alibaba.druid.util.JdbcUtils; */ public class DruidDataSource extends DruidAbstractDataSource implements DruidDataSourceMBean, ManagedDataSource, Referenceable { - private final static Log LOG = LogFactory.getLog(DruidDataSource.class); + private final static Log LOG = LogFactory.getLog(DruidDataSource.class); - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private final ReentrantLock lock = new ReentrantLock(); + private final ReentrantLock lock = new ReentrantLock(); - private final Condition notEmpty = lock.newCondition(); - private final Condition empty = lock.newCondition(); + private final Condition notEmpty = lock.newCondition(); + private final Condition empty = lock.newCondition(); // stats - private long connectCount = 0L; - private long closeCount = 0L; - private long connectErrorCount = 0L; - private long recycleCount = 0L; - private long createConnectionCount = 0L; - private long destroyCount = 0L; - private long removeAbandonedCount = 0L; - private long notEmptyWaitCount = 0L; - private long notEmptySignalCount = 0L; - private long notEmptyWaitNanos = 0L; + private long connectCount = 0L; + private long closeCount = 0L; + private long connectErrorCount = 0L; + private long recycleCount = 0L; + private long createConnectionCount = 0L; + private long destroyCount = 0L; + private long removeAbandonedCount = 0L; + private long notEmptyWaitCount = 0L; + private long notEmptySignalCount = 0L; + private long notEmptyWaitNanos = 0L; // store private ConnectionHolder[] connections; - private int poolingCount = 0; - private int activeCount = 0; + private int poolingCount = 0; + private int activeCount = 0; + private int notEmptyWaitThreadCount = 0; // threads private CreateConnectionThread createConnectionThread; private DestroyConnectionThread destoryConnectionThread; - private final CountDownLatch initedLatch = new CountDownLatch(2); + private final CountDownLatch initedLatch = new CountDownLatch(2); - private boolean enable = false; + private boolean enable = false; - private boolean resetStatEnable = true; + private boolean resetStatEnable = true; public DruidDataSource(){ } @@ -583,7 +584,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { while (poolingCount == 0) { empty.signal(); // send signal to CreateThread create connection - notEmpty.await(); // signal by recycle or creator + notEmptyWaitThreadCount++; + try { + notEmpty.await(); // signal by recycle or creator + } finally { + notEmptyWaitThreadCount--; + } notEmptyWaitCount++; if (!enable) { @@ -615,6 +621,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat throw new GetConnectionTimeoutException(); } + notEmptyWaitThreadCount++; try { long startEstimate = estimate; estimate = notEmpty.awaitNanos(estimate); // signal by recycle or creator @@ -629,6 +636,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat notEmpty.signal(); // propagate to non-interrupted thread notEmptySignalCount++; throw ie; + } finally { + notEmptyWaitThreadCount--; } if (poolingCount == 0) { @@ -720,10 +729,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { // 必须存在线程等待,才创建连接 - int waitThreadCount = lock.getWaitQueueLength(notEmpty); - - if (poolingCount >= waitThreadCount) { - notEmpty.signal(); // 防止信号丢失引起的等待 + if (poolingCount >= notEmptyWaitThreadCount) { notEmptySignalCount++; empty.await(); continue; diff --git a/src/test/java/com/alibaba/druid/benckmark/TestAtomicPerformance.java b/src/test/java/com/alibaba/druid/benckmark/TestAtomicPerformance.java new file mode 100644 index 0000000000..d358e034a4 --- /dev/null +++ b/src/test/java/com/alibaba/druid/benckmark/TestAtomicPerformance.java @@ -0,0 +1,45 @@ +package com.alibaba.druid.benckmark; + +import java.util.concurrent.atomic.AtomicInteger; + +import junit.framework.TestCase; + +public class TestAtomicPerformance extends TestCase { + + public void test_0() throws Exception { + AtomicInteger count = new AtomicInteger(); + for (int i = 0; i < 5; ++i) { + perf(count); + } + System.out.println(); + for (int i = 0; i < 5; ++i) { + perf2(count); + } + } + + private void perf(AtomicInteger count) { + long startMillis = System.currentTimeMillis(); + + count.set(0); + for (int i = 0; i < 1000 * 1000 * 100; ++i) { + int value = count.get(); + count.compareAndSet(value, value + 1); + } + + long millis = System.currentTimeMillis() - startMillis; + System.out.println("millis " + millis); + } + + private void perf2(AtomicInteger count) { + long startMillis = System.currentTimeMillis(); + + count.set(0); + for (int i = 0; i < 1000 * 1000 * 100; ++i) { + int value = count.get(); + count.weakCompareAndSet(value, value + 1); + } + + long millis = System.currentTimeMillis() - startMillis; + System.out.println("weak millis " + millis); + } +} 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 index b6adf3ad9d..861c1052a0 100644 --- 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 @@ -62,7 +62,7 @@ public class TestIdle3_Concurrent_Starvation extends TestCase { } for (int i = 0; i < 1; ++i) { - final int threadCount = 5; + final int threadCount = 10; concurrent(threadCount); }