diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 7512c70f..b0e18b55 100755 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -16,17 +16,27 @@ package com.zaxxer.hikari.pool; +import static com.zaxxer.hikari.pool.PoolEntry.LASTACCESS_COMPARABLE; +import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_IN_USE; +import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_NOT_IN_USE; +import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_REMOVED; +import static com.zaxxer.hikari.util.UtilityElf.createThreadPoolExecutor; +import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; +import static java.util.Collections.unmodifiableCollection; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLTransientConnectionException; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadLocalRandom; @@ -50,13 +60,6 @@ import com.zaxxer.hikari.util.ConcurrentBag.IBagStateListener; import com.zaxxer.hikari.util.SuspendResumeLock; import com.zaxxer.hikari.util.UtilityElf.DefaultThreadFactory; -import static com.zaxxer.hikari.pool.PoolEntry.LASTACCESS_COMPARABLE; -import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_IN_USE; -import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_NOT_IN_USE; -import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_REMOVED; -import static com.zaxxer.hikari.util.UtilityElf.createThreadPoolExecutor; -import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; - /** * This is the primary connection pool class that provides the basic * pooling behavior for HikariCP. @@ -80,6 +83,7 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL private final PoolEntryCreator POOL_ENTRY_CREATOR = new PoolEntryCreator(); private final AtomicInteger totalConnections; + private final Collection addConnectionQueue; private final ThreadPoolExecutor addConnectionExecutor; private final ThreadPoolExecutor closeConnectionExecutor; private final ScheduledThreadPoolExecutor houseKeepingExecutorService; @@ -118,6 +122,9 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL registerMBeans(this); ThreadFactory threadFactory = config.getThreadFactory(); + + LinkedBlockingQueue addConnectionQueue = new LinkedBlockingQueue<>(config.getMaximumPoolSize() + 1); + this.addConnectionQueue = unmodifiableCollection(addConnectionQueue); this.addConnectionExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), poolName + " connection adder", threadFactory, new ThreadPoolExecutor.DiscardPolicy()); this.closeConnectionExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), poolName + " connection closer", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy()); @@ -297,7 +304,12 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL @Override public Future addBagItem() { - return addConnectionExecutor.submit(POOL_ENTRY_CREATOR); + final int connectionsToAdd = connectionBag.getPendingQueue() - addConnectionQueue.size(); + if (connectionsToAdd > 0) { + return addConnectionExecutor.submit(POOL_ENTRY_CREATOR); + } + + return CompletableFuture.completedFuture(Boolean.TRUE); } // *********************************************************************** @@ -461,9 +473,9 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL private void fillPool() { final int connectionsToAdd = Math.min(config.getMaximumPoolSize() - totalConnections.get(), config.getMinimumIdle() - getIdleConnections()) - - addConnectionExecutor.getQueue().size(); + - addConnectionQueue.size(); for (int i = 0; i < connectionsToAdd; i++) { - addBagItem(); + addConnectionExecutor.submit(POOL_ENTRY_CREATOR); } if (connectionsToAdd > 0 && LOGGER.isDebugEnabled()) {