對象池透過復用昂貴對象(數據庫連接、線程、大對象)降低 GC 壓力與創建開銷。本文實現一個輕量級、線程安全、泛型通用的對象池,採用 ObjectUnit(單類型池)+ Provider(Singleton 目錄表)雙層架構。
items 存對象,checkedOut 標記借用狀態。semaphore:當前借出數,semaphore < items.size() 表示有空閒對象。synchronized 保證線程安全。public synchronized T checkOut() {
if (semaphore < items.size()) { // 有空閒
semaphore++;
return getItem(); // 尋找第一個未借出
}
return addItem(); // 池滿,創建新對象
}
public synchronized void checkIn(T x) {
if (releaseItem(x)) semaphore--; // 歸還成功遞減
}
ConcurrentHashMap<Class<?>, ObjectUnit<?>> 存儲各類型池。getObj(Class<T>) / renObj(T) 統一入口,內部委派給 ObjectUnit。public <T> T getObj(Class<T> key) {
ObjectUnit<?> unit = providers.get(key);
if (unit != null) return (T) unit.checkOut();
unit = new ObjectUnit<>(key);
providers.put(key, unit);
return (T) unit.addItem(); // 首次創建並直接借出
}
泛型擦除妥協: Map 使用 <?>,取出時需 @SuppressWarnings("unchecked") 強轉,屬無損運行時安全的編譯期妥協。
// 獲取連接池
Connection conn = Provider.getInstance().getObj(Connection.class);
try { ... } finally {
Provider.getInstance().renObj(conn); // 必須歸還
}