diff --git a/fine-druid/src/com/fr/third/alibaba/druid/pool/DruidDataSource.java b/fine-druid/src/com/fr/third/alibaba/druid/pool/DruidDataSource.java index 8fd1f3937..ef1481c9d 100644 --- a/fine-druid/src/com/fr/third/alibaba/druid/pool/DruidDataSource.java +++ b/fine-druid/src/com/fr/third/alibaba/druid/pool/DruidDataSource.java @@ -139,6 +139,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private DestroyTask destroyTask; private CreateConnectionThread createConnectionThread; + private PeriodDetectionThread periodDetectionThread; private DestroyConnectionThread destroyConnectionThread; private LogStatsThread logStatsThread; private int createTaskCount; @@ -607,16 +608,21 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat createConnectionThread = new CreateConnectionThread(threadName); createConnectionThread.setStarted(false); String destroyName = "Druid-ConnectionPool-Destroy-" + System.identityHashCode(this) + this.getUrl(); + if (destroyConnectionThread != null) { + if (!destroyConnectionThread.isInterrupted()) { + destroyConnectionThread.interrupt(); + } + } destroyConnectionThread = new DestroyConnectionThread(destroyName); destroyConnectionThread.setStarted(false); initedLatch = new CountDownLatch(2); } private void checkThread() throws SQLException { - if (createConnectionThread == null){ + if (createConnectionThread == null) { throw new IllegalStateException("createConnectionThread not start!"); } - if (destroyConnectionThread == null){ + if (destroyConnectionThread == null) { throw new IllegalStateException("destroyConnectionThread not start!"); } if (!createConnectionThread.isStarted() && !destroyConnectionThread.isStarted()) { @@ -780,7 +786,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat createAndLogThread(); createAndStartCreatorThread(); createAndStartDestroyThread(); - + createAndStartDetectThread(); initedLatch.await(); init = true; @@ -859,6 +865,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat initedLatch.countDown(); } + private void createAndStartDetectThread() { + if(createScheduler == null){ + String threadName = "Druid-ConnectionPool-Detection-" + System.identityHashCode(this) + this.getUrl(); + periodDetectionThread = new PeriodDetectionThread(threadName); + periodDetectionThread.start(); + } + } + /** * load filters from SPI ServiceLoader @@ -1526,7 +1540,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (destroyConnectionThread != null) { destroyConnectionThread.interrupt(); } - + if (periodDetectionThread != null){ + periodDetectionThread.interrupt(); + } if (destroySchedulerFuture != null) { destroySchedulerFuture.cancel(true); } @@ -2198,6 +2214,33 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat this.started = started; } } + //周期性检查生产线程状态,因为在终止生产线程的时候,为了不让生产线程疯狂重试数据库,只是生成了一个生产线程,但是并没有start,需要一个守护线程 + //周期性检查线程状态,帮助其启动。 + private class PeriodDetectionThread extends Thread { + public PeriodDetectionThread(String name) { + super(name); + this.setDaemon(true); + } + + public void run() { + while(true) { + synchronized (DruidDataSource.this) { + //生产线程发生了切换,并且有线程在等待连接,需要主动唤醒生产线程,否则由getConnection方法来唤醒生产线程 + if (!createConnectionThread.started && !destroyConnectionThread.started && notEmptyWaitThreadCount > 0) { + createConnectionThread.setStarted(true); + createConnectionThread.start(); + destroyConnectionThread.setStarted(true); + destroyConnectionThread.start(); + } + } + try { + Thread.sleep(30000); + } catch (InterruptedException ignore) { + break; + } + } + } + } public class DestroyConnectionThread extends Thread { private volatile boolean started = true;