coreconnectionpool.java
来自「Jodd是一个开源的公用Java基础类库」· Java 代码 · 共 192 行
JAVA
192 行
package jodd.db.pool;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
/**
* A class for preallocating, recycling, and managing JDBC connections.
*
* It uses threads for opening a new connection. When no connection
* availiable it will wait until a connection is released.
*
* @2do add thread for cleaning non-necessary connections, from time to time.
*/
public class CoreConnectionPool implements Runnable, ConnectionPool {
// ---------------------------------------------------------------- properties
private String driver;
public void setDriver(String s) {
driver = s;
}
private String url;
public void setUrl(String s) {
url = s;
}
private String user;
public void setUser(String s) {
user = s;
}
private String password;
public void setPassword(String s) {
password = s;
}
private int maxConnections = 10;
public void setMaxConnections(int i) {
maxConnections = i;
}
private int minConnections = 5;
public void setMinConnections(int i) {
minConnections = i;
}
private boolean waitIfBusy = false;
public void setWaitIfBusy(boolean b) {
waitIfBusy = b;
}
// ---------------------------------------------------------------- init
private ArrayList availableConnections, busyConnections;
private boolean connectionPending = false;
public CoreConnectionPool() {
}
public void init() throws SQLException {
try {
Class.forName(driver);
} catch (ClassNotFoundException cnfe) {
throw new SQLException("Database driver not found: " + driver);
}
if (minConnections > maxConnections) {
minConnections = maxConnections;
}
availableConnections = new ArrayList(minConnections);
busyConnections = new ArrayList();
for (int i = 0; i < minConnections; i++) {
availableConnections.add(DriverManager.getConnection(url, user, password));
}
}
// ---------------------------------------------------------------- get/free
public synchronized Connection getConnection() throws SQLException {
if (!availableConnections.isEmpty()) {
int lastIndex = availableConnections.size() - 1;
Connection existingConnection = (Connection) availableConnections.get(lastIndex);
availableConnections.remove(lastIndex);
// If connection on available list is closed (e.g., it timed out), then remove it from available list
// and repeat the process of obtaining a connection. Also wake up threads that were waiting for a
// connection because maxConnection limit was reached.
if (existingConnection.isClosed()) {
notifyAll(); // freed up a spot for anybody waiting
return getConnection();
} else {
busyConnections.add(existingConnection);
return existingConnection;
}
} else {
// Three possible cases:
// 1) You haven't reached maxConnections limit. So establish one in the background if there isn't
// already one pending, then wait for the next available connection (whether or not
// it was the newly established one).
// 2) You reached maxConnections limit and waitIfBusy flag is false. Throw SQLException in such a case.
// 3) You reached maxConnections limit and waitIfBusy flag is true. Then do the same thing as in second
// part of step 1: wait for next available connection.
if ((totalConnections() < maxConnections) && !connectionPending) {
makeBackgroundConnection();
} else if (!waitIfBusy) {
throw new SQLException("Connection limit reached");
}
// wait for either a new connection to be established (if you called makeBackgroundConnection) or for
// an existing connection to be freed up.
try {
wait();
} catch (InterruptedException ie) {
}
// someone freed up a connection, so try again.
return getConnection();
}
}
/**
* You can't just make a new connection in the foreground when none are
* available, since this can take several seconds with a slow network
* connection. Instead, start a thread that establishes a new connection,
* then wait. You get woken up either when the new connection is established
* or if someone finishes with an existing connection.
*/
private void makeBackgroundConnection() {
connectionPending = true;
try {
Thread connectThread = new Thread(this);
connectThread.start();
} catch (OutOfMemoryError oome) {
// give up on new connection
}
}
public void run() {
try {
Connection connection = DriverManager.getConnection(url, user, password);
synchronized(this) {
availableConnections.add(connection);
connectionPending = false;
notifyAll();
}
} catch (Exception e) { // SQLException or OutOfMemory
// give up on new connection and wait for existing one to free up.
}
}
public synchronized void freeConnection(Connection connection) {
busyConnections.remove(connection);
availableConnections.add(connection);
// wake up threads that are waiting for a connection
notifyAll();
}
public synchronized int totalConnections() {
return (availableConnections.size() + busyConnections.size());
}
// ---------------------------------------------------------------- close
/**
* Close all the connections. Use with caution: be sure no connections are in
* use before calling. Note that you are not <I>required</I> to call this
* when done with a ConnectionPool, since connections are guaranteed to be
* closed when garbage collected. But this method gives more control
* regarding when the connections are closed.
*/
public synchronized void close() {
closeConnections(availableConnections);
availableConnections = new ArrayList();
closeConnections(busyConnections);
busyConnections = new ArrayList();
}
private void closeConnections(ArrayList connections) {
try {
for (int i=0; i<connections.size(); i++) {
Connection connection = (Connection)connections.get(i);
if (!connection.isClosed()) {
connection.close();
}
}
} catch (SQLException sqle) {
// Ignore errors; garbage collect anyhow
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?