|
@@ -12,11 +12,31 @@ import java.sql.SQLFeatureNotSupportedException;
|
|
|
import java.time.Instant;
|
|
|
import java.util.concurrent.BlockingQueue;
|
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
+import java.util.concurrent.locks.ReentrantLock;
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
public class SimpleDataSource implements DataSource, AutoCloseable {
|
|
|
|
|
|
- private final BlockingQueue<SimpleConnection> pool = new LinkedBlockingQueue<>(300);
|
|
|
+ /**
|
|
|
+ * 默认最大连接
|
|
|
+ */
|
|
|
+ private final int MAX_IDLE = 300;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连接上限后最大等待时间(秒)
|
|
|
+ */
|
|
|
+ private final int MAX_WAIT_SECONDS = 3;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 活跃连接数
|
|
|
+ */
|
|
|
+ private AtomicInteger activeNum = new AtomicInteger(0);
|
|
|
+
|
|
|
+ private final ReentrantLock lock = new ReentrantLock();
|
|
|
+
|
|
|
+ private final BlockingQueue<SimpleConnection> pool = new LinkedBlockingQueue<>(MAX_IDLE);
|
|
|
/**
|
|
|
* 有效期(毫秒),默认60s
|
|
|
*/
|
|
@@ -39,21 +59,35 @@ public class SimpleDataSource implements DataSource, AutoCloseable {
|
|
|
|
|
|
@Override
|
|
|
public Connection getConnection() throws SQLException {
|
|
|
- SimpleConnection poll = pool.poll();
|
|
|
- if (null == poll) {
|
|
|
- return createConnection();
|
|
|
- }
|
|
|
-
|
|
|
- // 连接无效
|
|
|
- if (!poll.isValid(VALID_TIMEOUT_SECONDS)) {
|
|
|
- return createConnection();
|
|
|
- }
|
|
|
+ try {
|
|
|
+ lock.lock();
|
|
|
+ //如果当前连接数大于或等于最大连接数
|
|
|
+ if (activeNum.get() >= MAX_IDLE) {
|
|
|
+ //等待3秒
|
|
|
+ TimeUnit.SECONDS.sleep(MAX_WAIT_SECONDS);
|
|
|
+ if (activeNum.get() >= MAX_IDLE) {
|
|
|
+ throw new ConnectorException(String.format("数据库连接数超过上限%d,url=%s", MAX_IDLE, url));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ SimpleConnection poll = pool.poll();
|
|
|
+ if (null == poll) {
|
|
|
+ return createConnection();
|
|
|
+ }
|
|
|
+ // 连接无效
|
|
|
+ if (!poll.isValid(VALID_TIMEOUT_SECONDS)) {
|
|
|
+ return createConnection();
|
|
|
+ }
|
|
|
|
|
|
- // 连接过期
|
|
|
- if (isExpired(poll)) {
|
|
|
- return createConnection();
|
|
|
+ // 连接过期
|
|
|
+ if (isExpired(poll)) {
|
|
|
+ return createConnection();
|
|
|
+ }
|
|
|
+ return poll;
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ throw new ConnectorException(e);
|
|
|
+ } finally {
|
|
|
+ lock.unlock();
|
|
|
}
|
|
|
- return poll;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -103,6 +137,9 @@ public class SimpleDataSource implements DataSource, AutoCloseable {
|
|
|
|
|
|
public void close(Connection connection) {
|
|
|
if (connection != null && connection instanceof SimpleConnection) {
|
|
|
+
|
|
|
+ activeNum.decrementAndGet();
|
|
|
+
|
|
|
SimpleConnection simpleConnection = (SimpleConnection) connection;
|
|
|
// 连接过期
|
|
|
if (isExpired(simpleConnection)) {
|
|
@@ -132,7 +169,14 @@ public class SimpleDataSource implements DataSource, AutoCloseable {
|
|
|
* @throws SQLException
|
|
|
*/
|
|
|
private SimpleConnection createConnection() throws SQLException {
|
|
|
- return new SimpleConnection(DatabaseUtil.getConnection(driverClassName, url, username, password), StringUtil.equals(driverClassName, "oracle.jdbc.OracleDriver"));
|
|
|
+ SimpleConnection simpleConnection = null;
|
|
|
+ try {
|
|
|
+ simpleConnection = new SimpleConnection(DatabaseUtil.getConnection(driverClassName, url, username, password), StringUtil.equals(driverClassName, "oracle.jdbc.OracleDriver"));
|
|
|
+ activeNum.incrementAndGet();
|
|
|
+ } catch (SQLException e) {
|
|
|
+ throw new ConnectorException(e);
|
|
|
+ }
|
|
|
+ return simpleConnection;
|
|
|
}
|
|
|
|
|
|
}
|