diff --git a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java index a1337a6ad7..48365ad2b8 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSource.java @@ -7,7 +7,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executors; @@ -32,6 +31,7 @@ import com.alibaba.druid.pool.ha.valid.DataSourceFailureDetecter; import com.alibaba.druid.pool.ha.valid.DefaultDataSourceFailureDetecter; import com.alibaba.druid.proxy.jdbc.DataSourceProxy; import com.alibaba.druid.util.JdbcUtils; +import com.alibaba.druid.util.ThreadLocalRandom; public class MultiDataSource extends DataSourceAdapter implements MultiDataSourceMBean, DataSourceProxy { @@ -79,8 +79,6 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc private ConfigLoader configLoader; - private Random random; - private int maxPoolSize = 50; private long activeCount = 0; @@ -178,8 +176,6 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc return; } - random = new Random(); - initInternal(); scheduler = Executors.newScheduledThreadPool(schedulerThreadCount); @@ -377,7 +373,7 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc return 0; } - return random.nextInt(totalWeight); + return ThreadLocalRandom.current().nextInt(totalWeight); } public MultiConnectionHolder getRealConnection(MultiDataSourceConnection multiConn, String sql) throws SQLException { diff --git a/src/main/java/com/alibaba/druid/pool/ha/balance/WeightBalancer.java b/src/main/java/com/alibaba/druid/pool/ha/balance/WeightBalancer.java index 7bf785280d..d0e02d194a 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/balance/WeightBalancer.java +++ b/src/main/java/com/alibaba/druid/pool/ha/balance/WeightBalancer.java @@ -15,9 +15,9 @@ public class WeightBalancer implements Balancer { public MultiConnectionHolder getConnection(MultiDataSourceConnection connectionProxy, String sql) throws SQLException { MultiDataSource multiDataSource = connectionProxy.getMultiDataSource(); - + long maxWaitMillis = multiDataSource.getMaxWaitMillis(); - + long startNano = -1; if (maxWaitMillis > 0) { startNano = System.nanoTime(); @@ -91,7 +91,8 @@ public class WeightBalancer implements Balancer { } if (dataSource == null) { - throw new SQLException("cannot get connection. enabledDataSourceCount " + multiDataSource.getEnabledDataSourceCount()); + throw new SQLException("cannot get connection. enabledDataSourceCount " + + multiDataSource.getEnabledDataSourceCount()); } return dataSource.getConnection(); diff --git a/src/main/java/com/alibaba/druid/util/ThreadLocalRandom.java b/src/main/java/com/alibaba/druid/util/ThreadLocalRandom.java new file mode 100644 index 0000000000..1a29716fbb --- /dev/null +++ b/src/main/java/com/alibaba/druid/util/ThreadLocalRandom.java @@ -0,0 +1,193 @@ +package com.alibaba.druid.util; + + + +import java.util.Random; + +/** + * A random number generator isolated to the current thread. Like the + * global {@link java.util.Random} generator used by the {@link + * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized + * with an internally generated seed that may not otherwise be + * modified. When applicable, use of {@code ThreadLocalRandom} rather + * than shared {@code Random} objects in concurrent programs will + * typically encounter much less overhead and contention. Use of + * {@code ThreadLocalRandom} is particularly appropriate when multiple + * tasks (for example, each a {@link ForkJoinTask}) use random numbers + * in parallel in thread pools. + * + *
Usages of this class should typically be of the form: + * {@code ThreadLocalRandom.current().nextX(...)} (where + * {@code X} is {@code Int}, {@code Long}, etc). + * When all usages are of this form, it is never possible to + * accidently share a {@code ThreadLocalRandom} across multiple threads. + * + *
This class also provides additional commonly used bounded random
+ * generation methods.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class ThreadLocalRandom extends Random {
+ // same constants as Random, but must be redeclared because private
+ private static final long multiplier = 0x5DEECE66DL;
+ private static final long addend = 0xBL;
+ private static final long mask = (1L << 48) - 1;
+
+ /**
+ * The random seed. We can't use super.seed.
+ */
+ private long rnd;
+
+ /**
+ * Initialization flag to permit calls to setSeed to succeed only
+ * while executing the Random constructor. We can't allow others
+ * since it would cause setting seed in one part of a program to
+ * unintentionally impact other usages by the thread.
+ */
+ boolean initialized;
+
+ // Padding to help avoid memory contention among seed updates in
+ // different TLRs in the common case that they are located near
+ // each other.
+ private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
+
+ /**
+ * The actual ThreadLocal
+ */
+ private static final ThreadLocal