我已經實現了連接池。一切都很好。現在,如果一個客戶借用一個連接,甚至將其返回到池中,但客戶端也保持與他的連接的參考。現在,如果池返回與另一個客戶端相同的連接,這將導致多人使用相同的連接。避免客戶端在實現連接時保持連接的引用池
我該如何避免這種情況?
我已經實現了連接池。一切都很好。現在,如果一個客戶借用一個連接,甚至將其返回到池中,但客戶端也保持與他的連接的參考。現在,如果池返回與另一個客戶端相同的連接,這將導致多人使用相同的連接。避免客戶端在實現連接時保持連接的引用池
我該如何避免這種情況?
不要返回底層連接對象,而是返回包裝它的另一個對象。在該對象內(使用某種私有屬性)存儲該對象的狀態;是否仍然可以使用,還是因爲被退回游泳池或其他條件(如超時)而失效)。然後你可以攔截任何嘗試使用它的方法調用並檢查它的狀態。如果它不再可用,則拋出異常。
包裝的連接對象也需要是私有的,這樣客戶端才能直接訪問它。
每個客戶端都有一個包裝器,但兩個或多個包裝器可能共享底層連接對象。但是,由於每個客戶端都在存儲狀態,因此一次只能有一個客戶端使用該對象。
修改爲包含一個未經測試的示例 - 該示例現在顯示了我的方法存在的一個大問題。
假設你正在返回一些實現了java.sql.Connection的東西,你可以返回下面類的實例。
package same.package.as.your.pool; // so your pool has access to set isValidConnection
import java.sql.Connection;
class MyConnection implements Connection {
private Connection actualConnection;
private boolean isValidConnection = false;
MyConnection(Connection conn) {
// package acccess for pool class to create connection
actualConnection = conn;
isValidConnection = true;
}
public boolean getIsValidConnection() {
return isValidConnection;
}
void setIsValidConnection(boolean isValid) {
// pool class can call this to invalidate when returned to pool or timed out
isValidConnection = isValid;
}
// intercept java.sql.Connection methods, checking if connection is still valid first
// for example
PreparedStatement prepareStatement(String sql) {
if (! isValidConnection) {
// WHAT TO DO HERE?
}
return actualConnection.prepareStatement(sql);
}
// ... and the rest
第一個大問題就是 - 最好你會當連接不再有效,因爲它已經返回到池塘裏扔從像prepareStatement方法異常。但是由於受到捕獲的原始接口異常的限制(在本例中拋出SQLException),您需要拋出一個SQLException(yuk,它實際上不是一個SQLException)或一個未捕獲的異常(yuk - 客戶機代碼可能想要捕捉連接池不再有效的情況)或其他: - )
上述代碼的兩個其他問題 - 用於保護只能用於池代碼的方法的包訪問是不是很健壯。也許你可以創建MyConnection代碼作爲池代碼中的某種內部類。最後,必須重寫全部 java.sql.Connection接口將會很痛苦。
}
我不確定這是如何「真實」的連接池做到這一點,只是我的想法如何處理它。 –
你可以舉個例子!我瞭解包裝對象;但即使返回object()。getConnection()返回該對象;客戶端仍然可以參考。 – Deepak
你正在返回的類實例不應該有getConnection()。 –