物件池模式用於管理可重用物件的生命週期,避免頻繁建立/銷毀昂貴資源(如資料庫連線、執行緒、Socket 連線)帶來的效能開銷。核心操作:checkOut() 取得物件、checkIn() 歸還物件,池內部維護「可用」與「已借出」兩個集合,並提供驗證、過期機制確保物件有效性。
public abstract class ObjectPool<T> {
private final Vector<T> locked = new Vector<>(); // 已借出
private final Vector<T> unlocked = new Vector<>(); // 可用
protected abstract T create(); // 建立新物件
public abstract boolean validate(T o); // 驗證物件有效性
public abstract void expire(T o); // 使物件失效/銷毀
public synchronized T checkOut() {
// 1. 嘗試從可用集合取得有效物件
if (!unlocked.isEmpty()) {
Iterator<T> it = unlocked.iterator();
while (it.hasNext()) {
T t = it.next();
if (validate(t)) {
unlocked.remove(t);
locked.add(t);
return t;
} else {
unlocked.remove(t);
expire(t);
}
}
}
// 2. 池無可用物件,建立新物件
T t = create();
locked.add(t);
return t;
}
public synchronized void checkIn(T t) {
locked.remove(t);
if (validate(t)) {
unlocked.add(t);
} else {
expire(t);
}
}
}
public class JDBCConnectionPool extends ObjectPool<Connection> {
private final String url, user, password;
public JDBCConnectionPool(String driver, String url, String user, String password) {
try { Class.forName(driver).newInstance(); }
catch (Exception e) { throw new RuntimeException("載入驅動失敗", e); }
this.url = url; this.user = user; this.password = password;
}
@Override protected Connection create() {
try { return DriverManager.getConnection(url, user, password); }
catch (SQLException e) { throw new RuntimeException("建立連線失敗", e); }
}
@Override public boolean validate(Connection c) {
try { return !c.isClosed() && c.isValid(1); } // 1 秒超時驗證
catch (SQLException e) { return false; }
}
@Override public void expire(Connection c) {
try { if (c != null) c.close(); }
catch (SQLException e) { /* 忽略 */ }
}
// 測試主程式
public static void main(String[] args) {
JDBCConnectionPool pool = new JDBCConnectionPool(
"com.mysql.jdbc.Driver",
"jdbc:mysql://127.0.0.1:3306/test", "root", "123");
Connection conn = pool.checkOut();
try {
// 使用連線...
} finally {
pool.checkIn(conn); // 必須歸還
}
}
}
JDK 並發套件提供基於信號量的簡易池化骨架,適合輕量級場景:
class SimplePool<T> {
private final Semaphore available;
private final T[] items;
private final boolean[] used;
@SuppressWarnings("unchecked")
public SimplePool(int maxSize, Supplier<T> factory) {
available = new Semaphore(maxSize, true);
items = (T[]) new Object[maxSize];
used = new boolean[maxSize];
for (int i = 0; i < maxSize; i++) items[i] = factory.get();
}
public T borrow() throws InterruptedException {
available.acquire();
return getNextAvailable();
}
public void release(T item) {
if (markAsUnused(item)) available.release();
}
private synchronized T getNextAvailable() {
for (int i = 0; i < items.length; i++) {
if (!used[i]) { used[i] = true; return items[i]; }
}
return null; // 不會發生
}
private synchronized boolean markAsUnused(T item) {
for (int i = 0; i < items.length; i++) {
if (items[i] == item) {
if (used[i]) { used[i] = false; return true; }
else return false;
}
}
return false;
}
}
org.apache.commons.pool2,提供完整的池化介面與預設實作。