Java对象池案例

wen java案例 3

本文目录导读:

Java对象池案例

  1. 简单对象池实现(通用)
  2. 数据库连接池示例
  3. 使用示例 - 连接池客户端
  4. 基于Apache Commons Pool2的高级示例
  5. 现代实现建议
  6. 最佳实践建议

我来为你提供几个不同场景的Java对象池案例,从简单到复杂。

简单对象池实现(通用)

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
/**
 * 通用对象池
 */
public class ObjectPool<T> {
    private final BlockingQueue<T> pool;
    private final Supplier<T> factory;
    private final int maxSize;
    private int createdCount = 0;
    public ObjectPool(int maxSize, Supplier<T> factory) {
        this.maxSize = maxSize;
        this.factory = factory;
        this.pool = new LinkedBlockingQueue<>(maxSize);
    }
    /**
     * 从池中获取对象
     */
    public T borrow() throws InterruptedException {
        T obj = pool.poll();
        if (obj == null) {
            synchronized (this) {
                if (createdCount < maxSize) {
                    obj = factory.get();
                    createdCount++;
                }
            }
            if (obj == null) {
                obj = pool.poll(5, TimeUnit.SECONDS);
            }
        }
        return obj;
    }
    /**
     * 归还对象到池中
     */
    public void returnObject(T obj) {
        if (obj != null) {
            pool.offer(obj);
        }
    }
    /**
     * 池中可用对象数量
     */
    public int availableCount() {
        return pool.size();
    }
}

数据库连接池示例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
/**
 * 数据库连接池
 */
public class DatabaseConnectionPool {
    private static final Logger LOGGER = Logger.getLogger(DatabaseConnectionPool.class.getName());
    private final String url;
    private final String username;
    private final String password;
    private final int maxSize;
    private final ConcurrentLinkedQueue<Connection> idleConnections;
    private final AtomicInteger activeConnections = new AtomicInteger(0);
    public DatabaseConnectionPool(String url, String username, String password, int maxSize) {
        this.url = url;
        this.username = username;
        this.password = password;
        this.maxSize = maxSize;
        this.idleConnections = new ConcurrentLinkedQueue<>();
    }
    /**
     * 获取数据库连接
     */
    public Connection getConnection() throws SQLException {
        Connection conn = idleConnections.poll();
        if (conn == null && activeConnections.get() < maxSize) {
            // 尝试创建新连接
            synchronized (this) {
                if (activeConnections.get() < maxSize) {
                    conn = createConnection();
                    activeConnections.incrementAndGet();
                }
            }
        }
        if (conn == null) {
            // 等待其他连接被释放
            long timeout = 5000; // 5秒超时
            long startTime = System.currentTimeMillis();
            while (conn == null && System.currentTimeMillis() - startTime < timeout) {
                conn = idleConnections.poll();
                if (conn == null) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
        if (conn == null) {
            throw new SQLException("Connection pool exhausted, timeout waiting for connection");
        }
        // 验证连接是否有效
        if (!isValid(conn)) {
            closeConnection(conn);
            return getConnection(); // 递归获取新连接
        }
        return conn;
    }
    /**
     * 归还数据库连接
     */
    public void returnConnection(Connection conn) {
        if (conn != null) {
            if (isValid(conn)) {
                idleConnections.offer(conn);
            } else {
                closeConnection(conn);
                activeConnections.decrementAndGet();
            }
        }
    }
    /**
     * 关闭连接池
     */
    public void shutdown() {
        idleConnections.forEach(this::closeConnection);
        idleConnections.clear();
        activeConnections.set(0);
    }
    private Connection createConnection() throws SQLException {
        Connection conn = DriverManager.getConnection(url, username, password);
        // 启用自动提交
        conn.setAutoCommit(true);
        LOGGER.info("Created new database connection, total: " + activeConnections.get() + 1);
        return conn;
    }
    private boolean isValid(Connection conn) {
        try {
            return conn != null && !conn.isClosed() && conn.isValid(3);
        } catch (SQLException e) {
            return false;
        }
    }
    private void closeConnection(Connection conn) {
        try {
            if (conn != null && !conn.isClosed()) {
                conn.close();
            }
        } catch (SQLException e) {
            LOGGER.severe("Error closing connection: " + e.getMessage());
        }
    }
}

使用示例 - 连接池客户端

public class DatabaseConnectionPoolDemo {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydb";
        String username = "root";
        String password = "password";
        // 创建连接池,最大5个连接
        DatabaseConnectionPool pool = new DatabaseConnectionPool(url, username, password, 5);
        // 多线程使用连接池
        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executor.submit(() -> {
                Connection conn = null;
                try {
                    // 获取连接
                    conn = pool.getConnection();
                    // 执行数据库操作
                    try (Statement stmt = conn.createStatement();
                         ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
                        while (rs.next()) {
                            // 处理结果...
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                    // 归还连接
                    if (conn != null) {
                        pool.returnConnection(conn);
                    }
                }
            });
        }
        executor.shutdown();
        // 关闭连接池
        pool.shutdown();
    }
}

基于Apache Commons Pool2的高级示例

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import java.time.Duration;
/**
 * 使用Apache Commons Pool 2实现对象池
 */
public class AdvancedObjectPoolExample {
    // 模拟一个昂贵的资源对象
    public static class ExpensiveResource {
        private final String resourceId;
        private boolean inUse = false;
        public ExpensiveResource() {
            // 模拟创建成本
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            this.resourceId = "Resource-" + System.currentTimeMillis();
            System.out.println("Created new resource: " + resourceId);
        }
        public String getResourceId() {
            return resourceId;
        }
        public void doWork(String task) {
            System.out.println(resourceId + " processing: " + task);
            // 模拟工作
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        public void reset() {
            System.out.println(resourceId + " resetting state");
            this.inUse = false;
        }
    }
    /**
     * 对象池工厂
     */
    public static class ResourceFactory extends BasePooledObjectFactory<ExpensiveResource> {
        @Override
        public ExpensiveResource create() throws Exception {
            return new ExpensiveResource();
        }
        @Override
        public PooledObject<ExpensiveResource> wrap(ExpensiveResource resource) {
            return new DefaultPooledObject<>(resource);
        }
        @Override
        public void activateObject(PooledObject<ExpensiveResource> p) throws Exception {
            // 对象被借出时调用
            p.getObject().inUse = true;
        }
        @Override
        public void passivateObject(PooledObject<ExpensiveResource> p) throws Exception {
            // 对象被归还时调用
            p.getObject().inUse = false;
        }
        @Override
        public void destroyObject(PooledObject<ExpensiveResource> p) throws Exception {
            // 对象被销毁时调用
            System.out.println("Destroying resource: " + p.getObject().getResourceId());
        }
        @Override
        public boolean validateObject(PooledObject<ExpensiveResource> p) {
            // 验证对象是否有效
            return p.getObject() != null;
        }
    }
    public static void main(String[] args) throws Exception {
        // 配置对象池
        GenericObjectPoolConfig<ExpensiveResource> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(10);           // 最大对象数
        config.setMaxIdle(5);             // 最大空闲对象数
        config.setMinIdle(2);             // 最小空闲对象数
        config.setMaxWait(Duration.ofSeconds(5));  // 最大等待时间
        config.setBlockWhenExhausted(true);        // 池耗尽时阻塞
        // 创建对象池
        GenericObjectPool<ExpensiveResource> pool = new GenericObjectPool<>(new ResourceFactory(), config);
        pool.setTestOnBorrow(true);   // 借出时验证
        pool.setTestOnReturn(true);   // 归还时验证
        // 预热对象池
        pool.preparePool();
        System.out.println("Initial idle objects: " + pool.getNumIdle());
        System.out.println("Initial active objects: " + pool.getNumActive());
        // 使用对象
        try (ExpensiveResource resource = pool.borrowObject()) {
            resource.doWork("Task 1");
        } // try-with-resources 自动归还,但需要实现AutoCloseable
        // 或者手动归还
        ExpensiveResource resource = pool.borrowObject();
        try {
            resource.doWork("Task 2");
            // 业务逻辑...
        } finally {
            pool.returnObject(resource);
        }
        // 并发使用
        ExecutorService executor = Executors.newFixedThreadPool(15);
        for (int i = 0; i < 15; i++) {
            final int taskId = i;
            executor.submit(() -> {
                try {
                    ExpensiveResource r = pool.borrowObject();
                    try {
                        r.doWork("Concurrent Task " + taskId);
                    } finally {
                        pool.returnObject(r);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
        executor.awaitTermination(10, TimeUnit.SECONDS);
        // 统计信息
        System.out.println("Pool statistics:");
        System.out.println("  Active: " + pool.getNumActive());
        System.out.println("  Idle: " + pool.getNumIdle());
        System.out.println("  Created: " + pool.getCreatedCount());
        // 关闭池
        pool.close();
    }
}

现代实现建议

import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
/**
 * 泛型对象池,支持函数式接口
 */
public class GenericObjectPool<T> {
    private final ConcurrentLinkedDeque<PooledObject<T>> available = new ConcurrentLinkedDeque<>();
    private final AtomicInteger created = new AtomicInteger(0);
    private final int maxSize;
    private final Function<Void, T> factory;
    private final Consumer<T> resetFunction;
    private static class PooledObject<T> {
        final T object;
        boolean inUse;
        PooledObject(T object) {
            this.object = object;
        }
    }
    public GenericObjectPool(int maxSize, Function<Void, T> factory, Consumer<T> resetFunction) {
        this.maxSize = maxSize;
        this.factory = factory;
        this.resetFunction = resetFunction;
    }
    /**
     * 使用完后自动归还
     */
    public <R> R execute(Function<T, R> action) throws Exception {
        T obj = borrow();
        try {
            return action.apply(obj);
        } finally {
            if (obj != null) {
                returnObject(obj);
            }
        }
    }
    private T borrow() throws Exception {
        // 尝试从代池获取
        PooledObject<T> pooledObj = available.poll();
        if (pooledObj != null) {
            return pooledObj.object;
        }
        // 创建新对象
        if (created.get() < maxSize) {
            synchronized (this) {
                if (created.get() < maxSize) {
                    T obj = factory.apply(null);
                    created.incrementAndGet();
                    return obj;
                }
            }
        }
        // 等待有对象归还
        while (true) {
            pooledObj = available.poll();
            if (pooledObj != null) {
                return pooledObj.object;
            }
            Thread.sleep(1); // 简单等待
        }
    }
    private void returnObject(T obj) {
        if (obj != null) {
            if (resetFunction != null) {
                try {
                    resetFunction.accept(obj);
                } catch (Exception e) {
                    // 重置失败,考虑销毁对象
                    return;
                }
            }
            available.offer(new PooledObject<>(obj));
        }
    }
    // 使用示例
    public static void main(String[] args) throws Exception {
        GenericObjectPool<StringBuilder> pool = new GenericObjectPool<>(
            5,
            v -> new StringBuilder(1024),
            sb -> sb.setLength(0)  // 重置内容
        );
        // 使用
        String result = pool.execute(sb -> {
            sb.append("Hello");
            sb.append(" World");
            return sb.toString();
        });
        System.out.println(result);
    }
}

最佳实践建议

  1. 选择合适的池化框架:Apache Commons Pool 2 或 HikariCP 是成熟的选择
  2. 设置合理的池大小:太大会浪费资源,太小会影响性能
  3. 实现对象验证:确保归还的对象是可用的
  4. 处理对象创建失败:实现重试机制
  5. 监控池状态:记录池的使用情况和性能指标
  6. 考虑使用try-with-resources:确保对象正确归还
  7. 实现池预热:在应用启动时预创建一些对象

对象池的主要目的是提高性能,特别是当对象创建成本高时(如数据库连接、网络连接、线程等),在实现时要特别注意线程安全和异常处理。

抱歉,评论功能暂时关闭!