gpt4 book ai didi

java - 我们自己实现了连接池,但是为什么总是断线呢?

转载 作者:行者123 更新时间:2023-12-01 16:41:38 25 4
gpt4 key购买 nike

源代码如下:

//public class ConnectionPool implements Runnable
public class ConnectionPool {
private static Logger loger_error = Logger.getLogger("error");
// JDBC Driver name
String driverName;

// JDBC Connection URL
String connectionURL;

// Minimum size of the pool
int connectionPoolSize;

// Maximum size of the pool
int connectionPoolMax;

// Maximum number of uses for a single connection, or -1 for none
int connectionUseCount;

// Maximum connection idle time (in minutes)
int connectionTimeout;

// Additional JDBC properties
String userName;

String password;

// The Connection pool. This is a vector of ConnectionObject
// objects
Vector pool;

// The maximum number of simultaneous connections as reported
// by the JDBC driver
int maxConnections = -1;

// Scheduler scheduler;

// Timeout value
public static int TIMEOUT_MS = 20000;

/**
* Initializes the ConnectionPool object using 'ConnectionPool.cfg' as the
* configuration file
*
* @return true if the ConnectionPool was initialized properly
*/
/*
* public boolean initialize() throws Exception { return
* initialize("com/omh/jdbc/ConnectionPool.cfg"); }
*/

/**
* Initializes the ConnectionPool object with the specified configuration
* file
*
* @param config
* Configuration file name
* @return true if the ConnectionPool was initialized properly
*/
public void initialize(String driverName, String connectionURL,
int connectionPoolSize, int connectionPoolMax,
int connectionUseCount, int connectionTimeout, String userName,
String password) throws Exception {
this.driverName = driverName;
this.connectionURL = connectionURL;
this.connectionPoolSize = connectionPoolSize;
this.connectionPoolMax = connectionPoolMax;
this.connectionUseCount = connectionUseCount;
this.connectionTimeout = connectionTimeout;
this.userName = userName;
this.password = password;

createPool();

// scheduler = new Scheduler();
// scheduler.schedule(this, TIMEOUT_MS);

}

/**
* Destroys the pool and it's contents. Closes any open JDBC connections and
* frees all resources
*/
public void destroy() {
try {
// Clear our pool
if (pool != null) {
// Loop throught the pool and close each connection
for (int i = 0; i < pool.size(); i++) {
((MangoDBConnection) pool.elementAt(i)).closeConnection();
}
}
pool = null;
} catch (Exception ex) {
ex.printStackTrace();
}
}

/**
* Gets an available JDBC Connection. Connections will be created if
* necessary, up to the maximum number of connections as specified in the
* configuration file.
*
* @return JDBC Connection, or null if the maximum number of connections has
* been exceeded
*/
public synchronized MangoDBConnection getConnection() {
// If there is no pool it must have been destroyed
if (pool == null) {
return null;
}

MangoDBConnection connectionObject = null;
int poolSize = pool.size();

// Get the next available connection
for (int i = 0; i < poolSize; i++) {
// Get the ConnectionObject from the pool
MangoDBConnection co = (MangoDBConnection) pool.elementAt(i);

// If this is a valid connection and it is not in use,
// grab it
if (co.isAvailable()) {
connectionObject = co;
break;
}
}

// No more available connections. If we aren't at the
// maximum number of connections, create a new entry
// in the pool
if (connectionObject == null) {
if ((connectionPoolMax < 0)
|| ((connectionPoolMax > 0) && (poolSize < connectionPoolMax))) {
// Add a new connection.
int i = addConnection();

// If a new connection was created, use it
if (i >= 0) {
connectionObject = (MangoDBConnection) pool.elementAt(i);
}
} else {
LogManager.log("Maximum number of connections exceeded");
loger_error.error("Maximum number of connections exceeded");
}
}

// If we have a connection, set the last time accessed,
// the use count, and the in use flag
if (connectionObject != null) {
connectionObject.use();
connectionObject.touch();
}

return connectionObject;
}

/**
* Places the connection back into the connection pool, or closes the
* connection if the maximum use count has been reached
*
* @param Connection
* object to close
*/

public synchronized void releaseConnection(MangoDBConnection con) {
removeFromPool(con);
}

public synchronized void release(MangoDBConnection con) {
if ((connectionUseCount > 0)
&& (con.getUseCount() >= connectionUseCount)) {
removeFromPool(con);
// add new connection upon releasing one
addConnection();
} else {
con.touch();
con.free();
}
/*
* // Find the connection in the pool int index = find(con);
* System.out.println("close"); if (index != -1) { ConnectionObject co =
* (ConnectionObject) pool.elementAt(index);
* // If the use count exceeds the max, remove it from // the pool. if
* ((connectionUseCount > 0) && (co.useCount >= connectionUseCount)) {
* trace("Connection use count exceeded"); removeFromPool(index); } else { //
* Clear the use count and reset the time last used co.touch();
* co.free(); } }
*/
}

/**
* Prints the contents of the connection pool to the standard output device
*/
public void printPool() {
printPool(new PrintWriter(System.out));
}

/**
* Prints the contents of the connection pool to the given PrintWriter
*/
public void printPool(PrintWriter out) {
out.println("--ConnectionPool--");
if (pool != null) {
for (int i = 0; i < pool.size(); i++) {
MangoDBConnection co = (MangoDBConnection) pool.elementAt(i);
out.println("" + i + "=" + co);
}
}
}

/**
* Returns an enumeration of the ConnectionObject objects that represent the
* pool
*/
public Enumeration getConnectionPoolObjects() {
return pool.elements();
}

public int returnConnectionCount() {
return connectionUseCount;
}

public int returnMaxPoolSize() {
return connectionPoolMax;
}

public int returnInitPoolSize() {
return connectionPoolSize;
}

/**
* Removes the ConnectionObject from the pool at the given index
*
* @param index
* Index into the pool vector
*/
private synchronized void removeFromPool(MangoDBConnection con) {
// Make sure the pool and index are valid
if (pool != null) {
con.closeConnection();
pool.removeElement(con);
}
}

/**
* Creates the initial connection pool. A timer thread is also created so
* that connection timeouts can be handled.
*
* @return true if the pool was created
*/
private void createPool() throws Exception {
// Dump the parameters we are going to use for the pool.
// We don't know what type of servlet environment we will
// be running in - this may go to the console or it
// may be redirected to a log file
LogManager.log("JDBCDriver = " + driverName);
LogManager.log("JDBCConnectionURL = " + connectionURL);
LogManager.log("ConnectionPoolSize = " + connectionPoolSize);
LogManager.log("ConnectionPoolMax = " + connectionPoolMax);
LogManager.log("ConnectionUseCount = " + connectionUseCount);
LogManager.log("ConnectionTimeout = " + connectionTimeout + " seconds");
LogManager.log("Registering " + driverName);

Driver d = (Driver) Class.forName(driverName).newInstance();

// Create the vector for the pool
pool = new Vector();

// Bring the pool to the minimum size
fillPool(connectionPoolSize);
}

/**
* Adds a new connection to the pool
*
* @return Index of the new pool entry, or -1 if an error has occurred
*/
public int addConnection() {
int index = -1;

try {
// Calculate the new size of the pool
int size = pool.size() + 1;

// Create a new entry
fillPool(size);

// Set the index pointer to the new connection if one
// was created
if (size == pool.size()) {
index = size - 1;
}
} catch (Exception ex) {
System.out.println("SSSSSSS");
ex.printStackTrace();
}
return index;
}

/**
* Brings the pool to the given size
*/
private synchronized void fillPool(int size) throws Exception {
String userID = this.userName;
String password = this.password;

// userID = getPropertyIgnoreCase(JDBCProperties, "user");
// password = getPropertyIgnoreCase(JDBCProperties, "password");

// Loop while we need to create more connections
while (pool.size() < size) {
MangoDBConnection co = new MangoDBConnectionMSSQL();

// Create the connection
co.makeConnection(connectionURL, userID, password);

// Do some sanity checking on the first connection in
// the pool
if (pool.size() == 0) {
// Get the maximum number of simultaneous connections
// as reported by the JDBC driver
maxConnections = co.getMaxConnections();
}

// Give a warning if the size of the pool will exceed
// the maximum number of connections allowed by the
// JDBC driver
if ((maxConnections > 0) && (size > maxConnections)) {
LogManager
.log("WARNING: Size of pool will exceed safe maximum of "
+ maxConnections);
}

// Clear the in use flag
co.free();
// Set the last access time
co.touch();

pool.addElement(co);
}

} // fillPool()

/**
* Gets a the named propery, ignoring case. Returns null if not found
*
* @param p
* The property set
* @param name
* The property name
* @return The value of the propery, or null if not found
*/
private String getPropertyIgnoreCase(Properties p, String name) {
if ((p == null) || (name == null))
return null;

String value = null;

// Get an enumeration of the property names
Enumeration enumeration = p.propertyNames();

// Loop through the enum, looking for the given property name
while (enumeration.hasMoreElements()) {
String pName = (String) enumeration.nextElement();
if (pName.equalsIgnoreCase(name)) {
value = p.getProperty(pName);
break;
}
}

return value;
}

/**
* Called by the timer each time a clock cycle expires. This gives us the
* opportunity to timeout connections
*/
/*
* public synchronized void run() { // No pool means no work if (pool ==
* null) { return; }
* // Get the current time in milliseconds long now =
* System.currentTimeMillis();
* // Check for any expired connections and remove them for (int i =
* pool.size() - 1; i >= 0; i--) { ConnectionObject co = (ConnectionObject)
* pool.elementAt(i);
* // If the connection is not in use and it has not been // used recently,
* remove it if (!co.inUse) { if ((connectionTimeout > 0) && (co.lastAccess +
* (connectionTimeout * 1000) < now)) { removeFromPool(i); } } }
* // Remove any connections that are no longer open for (int i =
* pool.size() - 1; i >= 0; i--) { ConnectionObject co = (ConnectionObject)
* pool.elementAt(i); try { // If the connection is closed, remove it from
* the pool if (co.con.isClosed()) { trace("Connection closed
* unexpectedly"); removeFromPool(i); } } catch (Exception ex) { } }
* // Now ensure that the pool is still at it's minimum size try { if (pool !=
* null) { if (pool.size() < connectionPoolSize) {
* fillPool(connectionPoolSize); } } } catch (Exception ex) {
* ex.printStackTrace(); }
* // Reschedule ourselves scheduler.schedule(this, TIMEOUT_MS); }
*/

}

大家有什么好主意吗?如何实现连接池?

最佳答案

资源池(如连接池)中资源泄漏的常见原因是池中的某些客户端在某些情况下无法释放资源。这是一个例子:

Resource resource = pool.getResource();
...
// do stuff
...
pool.releaseResource(resource);

如果在“do stuff”部分抛出异常并允许传播,这将泄漏资源。上述的非泄漏版本是:

Resource resource = pool.getResource();
try {
...
// do stuff
...
} finally {
pool.releaseResource(resource);
}

编辑:正如@Adamski 指出的那样,没有“ Elixir ”解决方案可以解决此类问题。我能建议的最好方法是执行以下操作:

  1. 搜索您的代码库以查找从池中请求资源的所有位置。然后从每一点开始,检查是否有泄漏并修复;例如基于上述模式。
  2. 创建一个测试套件来测试您的所有请求类型并针对您的服务重复运行

还有一件事。不要试图通过使用终结器来处理丢失的资源来“修复”问题。这可能会让问题看起来消失,但稍后当您的系统负载过重或重要人物正在观看您进行演示时,问题就会再次出现。

关于java - 我们自己实现了连接池,但是为什么总是断线呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1592488/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com