cra*_*ace 15 java connection pooling
在我面临的一次采访中,我被要求实施连接池.所以方法是这样的:
List或HashMapConnectionImpl getConnection()方法时,ConnectionPoolingImpl返回一个连接引用.现在当有人返回connection(releaseConnection(ConnectionImpl O))时,如何确保当同一个应用程序再次尝试重用连接对象时,我的实现会引发异常?
可能已将相同的连接对象返回到新应用程序,并且应该能够使用它.
我的观点是在每个Connectionimpl对象的另一个数组类型的结构中维护一个标志变量,并将该变量设置为有效值.当用户返回连接对象时,我会将其设为无效值.对于我的每个操作ConnectionImpl,我都必须验证用户是否有有效标志.
你会对这种方法说些什么?
gus*_*afc 23
我不会从池中返回"真正的"连接对象,而是一个包装器,它提供连接生命周期的池控制,而不是客户端.
假设您有一个非常简单的连接,您可以从中读取int值:
interface Connection {
int read(); // reads an int from the connection
void close(); // closes the connection
}
Run Code Online (Sandbox Code Playgroud)
从流中读取的实现可能如下所示(忽略异常,EOF处理等):
class StreamConnection implements Connection {
private final InputStream input;
int read(){ return input.read(); }
void close(){ input.close(); }
}
Run Code Online (Sandbox Code Playgroud)
此外,让我们假设你有一个StreamConnection看起来像这样的s 池(再次,忽略异常,并发等):
class StreamConnectionPool {
List<StreamConnection> freeConnections = openSomeConnectionsSomehow();
StreamConnection borrowConnection(){
if (freeConnections.isEmpty()) throw new IllegalStateException("No free connections");
return freeConnections.remove(0);
}
void returnConnection(StreamConnection conn){
freeConnections.add(conn);
}
}
Run Code Online (Sandbox Code Playgroud)
这里的基本想法是好的,但我们不能确定返回的连接,我们不能确保它们不会关闭,然后返回,或者你不回这些来自其他来源完全的连接.
解决方案是(当然)另一层间接:创建一个返回包装器的池Connection,而不是在close()调用时关闭底层连接,将其返回到池:
class ConnectionPool {
private final StreamConnectionPool streamPool = ...;
Connection getConnection() {
final StreamConnection realConnection = streamPool.borrowConnection();
return new Connection(){
private boolean closed = false;
int read () {
if (closed) throw new IllegalStateException("Connection closed");
return realConnection.read();
}
void close() {
if (!closed) {
closed = true;
streamPool.returnConnection(realConnection);
}
}
protected void finalize() throws Throwable {
try {
close();
} finally {
super.finalize();
}
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
这ConnectionPool将是客户端代码所见到的唯一内容.假设它是唯一的所有者StreamConnectionPool,这种方法有几个优点:
降低复杂性和对客户端代码的影响最小 -自己打开连接,并使用池之间唯一的区别是,你使用一个工厂弄个ConnectionS(您可能已经这样做了,如果你使用依赖注入).最重要的是,您始终以相同的方式清理资源,即通过呼叫close().就像你不关心read它做什么一样,只要它能为你提供所需的数据,你就不在乎close()它做什么,只要它释放你声称的资源.您不必考虑此连接是否来自池.
防止恶意/不正确使用 - 客户端只能返回他们从池中检索到的资源; 他们无法关闭基础联系; 他们不能使用他们已经返回的连接......等等
"保证"返回资源 - 由于我们的finalize实施,即使所有对借用的引用Connection都丢失了,它仍然会返回到池中(或者至少有机会被退回).当然,连接将以这种方式保持不必要的时间 - 可能是无限期的,因为最终确定无法保证 - 但这只是一个很小的改进.