首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 手寫通用對象池:基於信號量與 Singleton 的線程安全實現

     編輯:Java 相關知識

對象池透過復用昂貴對象(數據庫連接、線程、大對象)降低 GC 壓力與創建開銷。本文實現一個輕量級、線程安全、泛型通用的對象池,採用 ObjectUnit(單類型池)+ Provider(Singleton 目錄表)雙層架構。

核心設計

ObjectUnit<T>:單類型對象容器

  • 雙列表: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--; // 歸還成功遞減
}

Provider:全局 Singleton 目錄表

  • ConcurrentHashMap<Class<?>, ObjectUnit<?>> 存儲各類型池。
  • 雙重檢查鎖實現懶漢式 Singleton。
  • 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); // 必須歸還
}

生產級擴展建議

  1. 池大小上限:防止無限增長導致 OOM。
  2. 空閒對象驗證/回收:定時任務檢測連接有效性、超時釋放。
  3. 統計監控:命中率、等待時間、活躍數暴露給 Prometheus。
  4. 替換成熟框架:HikariCP(連接池)、Apache Commons Pool 2(通用池)已解決上述所有問題,**生產環境首選成熟庫**。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved