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

Java 設計模式:物件池模式實作與 JDBC 連線池範例

     編輯:Java 程式設計入門

模式意圖

物件池模式用於管理可重用物件的生命週期,避免頻繁建立/銷毀昂貴資源(如資料庫連線、執行緒、Socket 連線)帶來的效能開銷。核心操作:checkOut() 取得物件、checkIn() 歸還物件,池內部維護「可用」與「已借出」兩個集合,並提供驗證、過期機制確保物件有效性。

抽象基類 ObjectPool<T>

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);
        }
    }
}

JDBC 連線池實作

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); // 必須歸還
        }
    }
}

Java 內建替代方案:java.util.concurrent.Semaphore

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;
    }
}

生產環境建議

  • 優先使用成熟連線池庫:HikariCP(高效能)、Druid(監控強)、Apache DBCP2。
  • 自行實作時需考慮:最大/最小閒置連線數、連線存活檢測、洩漏偵測、聲明緩存、公平鎖與非公平鎖選擇。
  • 物件池通用化可參考 org.apache.commons.pool2,提供完整的池化介面與預設實作。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved