Hutool Hutool
(opens new window)
🏡首页
📖指南
🎢最佳实践
💖支持
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
(opens new window)
🏡首页
📖指南
🎢最佳实践
💖支持
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
  • 快速入门

  • 核心(hutool-core)

    • AI(Hutool-ai)

    • 注解(annotation)

    • 数组(array)

    • JavaBean(bean)

    • 缓存(cache)

    • 类加载器(classloader)

    • 编码解码(codec)

    • 集合(collection)

    • 比较器(comparator)

    • 压缩(compress)

    • 类型转换(convert)

    • 数据(data)

    • 日期时间(date)

    • 异常(exception)

    • 函数(func)

    • IO流(io)

    • 语言特性(lang)

    • Map(map)

    • 数字数学(math)

    • 网络(net)

    • 对象池(pool)

      • 对象池
      • 对象池架构设计
      • 对象池使用
        • 1. 基本使用
          • 1.1 创建简单对象池
          • 1.2 基本流程说明
        • 2. 自定义对象工厂
          • 2.1 复杂对象工厂示例
          • 2.2 使用自定义对象工厂
        • 3. 配置对象池
          • 3.1 基本配置
          • 3.2 配置说明
          • 3.3 动态调整配置
        • 4. 高级用法
          • 4.1 自定义分区分配策略
          • 4.2 自定义阻塞队列
          • 4.3 对象池监控
        • 5. 最佳实践
          • 5.1 资源管理
          • 5.2 配置优化
          • 5.3 线程安全
          • 5.4 性能考虑
        • 6. 常见问题
          • 6.1 对象池满了怎么办?
          • 6.2 如何处理无效对象?
          • 6.3 对象池支持哪些类型的对象?
        • 7. 完整示例
        • 8. 总结
    • 反射(reflect)

    • 正则(regex)

    • 服务提供(spi)

    • 聚合操作(stream)

    • 字符串文本(text)

    • 并发和线程(thread)

    • 树结构(tree)

    • 工具集合(util)

    • XML操作(xml)

  • 定时任务(hutool-cron)

  • 加密(hutool-crypto)

  • 数据库(hutool-db)

  • 扩展(hutool-extra)

  • HTTP(hutool-http)

  • 日志(hutool-log)

  • 配置文件(hutool-setting)

  • JSON(hutool-json)

  • Office办公(hutool-poi)

  • 套接字(hutool-socket)

  • GUI(hutool-swing)

  • 指南
  • 核心(hutool-core)
  • 对象池(pool)
Hutool
2026-01-24
目录

对象池使用

Hutool的对象池实现提供了高效、线程安全的对象管理机制。本教程将详细介绍如何使用Hutool的对象池,包括基本使用、自定义对象工厂、配置对象池以及高级用法。

# 1. 基本使用

# 1.1 创建简单对象池

首先,我们需要创建一个对象工厂,用于自定义对象的创建、验证和销毁逻辑:

import cn.hutool.v7.core.pool.ObjectFactory;

// 自定义对象工厂
public class SimpleObjectFactory implements ObjectFactory<StringBuilder> {
    @Override
    public StringBuilder create() {
        // 创建新对象
        return new StringBuilder();
    }

    @Override
    public boolean validate(StringBuilder obj) {
        // 验证对象是否可用
        // 这里简单返回true,表示所有对象都可用
        return true;
    }

    @Override
    public void destroy(StringBuilder obj) {
        // 销毁对象,这里清空StringBuilder
        obj.setLength(0);
    }
}

然后,我们可以创建并使用对象池:

import cn.hutool.v7.core.pool.ObjectPool;
import cn.hutool.v7.core.pool.partition.PartitionObjectPool;
import cn.hutool.v7.core.pool.partition.PartitionPoolConfig;

// 创建对象池配置
PartitionPoolConfig config = new PartitionPoolConfig();

// 创建对象工厂
SimpleObjectFactory factory = new SimpleObjectFactory();

// 创建对象池
ObjectPool<StringBuilder> pool = new PartitionObjectPool<>(config, factory);

// 借出对象
StringBuilder builder = pool.borrowObject();
try {
    // 使用对象
    builder.append("Hello");
    builder.append(" ");
    builder.append("Hutool");
    Console.log(builder.toString());
} finally {
    // 归还对象
    pool.returnObject(builder);
}

// 关闭对象池
pool.close();

# 1.2 基本流程说明

  1. 创建配置:创建PartitionPoolConfig对象,配置对象池的大小、等待时间等参数
  2. 创建工厂:实现ObjectFactory接口,定义对象的创建、验证和销毁逻辑
  3. 创建对象池:使用配置和工厂创建PartitionObjectPool实例
  4. 借出对象:调用borrowObject()方法从池中获取对象
  5. 使用对象:在try块中使用对象
  6. 归还对象:在finally块中调用returnObject()方法归还对象
  7. 关闭对象池:不再使用时,调用close()方法关闭对象池

# 2. 自定义对象工厂

# 2.1 复杂对象工厂示例

下面是一个更复杂的对象工厂示例,用于管理数据库连接:

import cn.hutool.v7.core.pool.ObjectFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionFactory implements ObjectFactory<Connection> {
    private final String url;
    private final String username;
    private final String password;

    public ConnectionFactory(String url, String username, String password) {
        this.url = url;
        this.username = username;
        this.password = password;
        // 加载数据库驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Failed to load JDBC driver", e);
        }
    }

    @Override
    public Connection create() {
        try {
            // 创建数据库连接
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            throw new RuntimeException("Failed to create database connection", e);
        }
    }

    @Override
    public boolean validate(Connection conn) {
        try {
            // 验证连接是否可用
            return !conn.isClosed() && conn.isValid(1);
        } catch (SQLException e) {
            return false;
        }
    }

    @Override
    public void destroy(Connection conn) {
        try {
            // 关闭数据库连接
            conn.close();
        } catch (SQLException e) {
            // 忽略关闭异常
        }
    }
}

# 2.2 使用自定义对象工厂

// 创建数据库连接工厂
ConnectionFactory factory = new ConnectionFactory(
    "jdbc:mysql://localhost:3306/test",
    "username",
    "password"
);

// 创建对象池
ObjectPool<Connection> pool = new PartitionObjectPool<>(new PartitionPoolConfig(), factory);

// 借出连接
Connection conn = pool.borrowObject();
try {
    // 使用连接执行SQL查询
    // ...
} finally {
    // 归还连接
    pool.returnObject(conn);
}

# 3. 配置对象池

# 3.1 基本配置

PartitionPoolConfig提供了以下配置项:

// 创建配置
PartitionPoolConfig config = new PartitionPoolConfig();

// 设置最小池大小(初始大小)
config.setMinSize(10);

// 设置最大池大小
config.setMaxSize(50);

// 设置最长等待时间(毫秒)
config.setMaxWait(10000);

// 设置最长空闲时间(毫秒)
config.setMaxIdle(30000);

// 设置分区数量
config.setPartitionSize(4);

# 3.2 配置说明

配置项 描述 默认值 建议值
minSize 最小池大小 5 10-20
maxSize 最大池大小 20 50-100
maxWait 最长等待时间(毫秒) 5000 5000-10000
maxIdle 最长空闲时间(毫秒) 0 30000-60000
partitionSize 分区数量 2 2-8

# 3.3 动态调整配置

在创建对象池后,我们可以通过对象池的方法获取当前状态,以便动态调整配置:

// 获取当前对象池状态
int total = pool.getTotal();
int idle = pool.getIdleCount();
int active = pool.getActiveCount();

System.out.printf("Total: %d, Idle: %d, Active: %d%n", total, idle, active);

# 4. 高级用法

# 4.1 自定义分区分配策略

默认情况下,Hutool的对象池根据线程ID分配分区。我们可以通过继承PartitionObjectPool类,自定义分区分配策略:

import cn.hutool.v7.core.pool.partition.PartitionObjectPool;
import cn.hutool.v7.core.pool.partition.PartitionPoolConfig;
import cn.hutool.v7.core.pool.ObjectFactory;

public class CustomPartitionPool<T> extends PartitionObjectPool<T> {
    public CustomPartitionPool(PartitionPoolConfig config, ObjectFactory<T> factory) {
        super(config, factory);
    }

    @Override
    protected int getPartitionIndex(PartitionPoolConfig poolConfig) {
        // 自定义分区分配策略:根据线程名称哈希值分配
        return Math.abs(Thread.currentThread().getName().hashCode()) % poolConfig.getPartitionSize();
    }
}

# 4.2 自定义阻塞队列

默认情况下,Hutool的对象池使用ArrayBlockingQueue作为阻塞队列。我们可以通过继承PartitionObjectPool类,自定义阻塞队列:

import cn.hutool.v7.core.pool.partition.PartitionObjectPool;
import cn.hutool.v7.core.pool.partition.PartitionPoolConfig;
import cn.hutool.v7.core.pool.Poolable;
import cn.hutool.v7.core.pool.ObjectFactory;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class CustomQueuePool<T> extends PartitionObjectPool<T> {
    public CustomQueuePool(PartitionPoolConfig config, ObjectFactory<T> factory) {
        super(config, factory);
    }

    @Override
    protected BlockingQueue<Poolable<T>> createBlockingQueue(PartitionPoolConfig poolConfig) {
        // 使用LinkedBlockingQueue替代默认的ArrayBlockingQueue
        return new LinkedBlockingQueue<>();
    }
}

# 4.3 对象池监控

我们可以定期监控对象池的状态,以便及时调整配置:

// 监控对象池状态
Runnable monitorTask = () -> {
    while (true) {
        try {
            int total = pool.getTotal();
            int idle = pool.getIdleCount();
            int active = pool.getActiveCount();

            System.out.printf("[%s] Total: %d, Idle: %d, Active: %d%n",
                new Date(), total, idle, active);

            // 休眠10秒
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            break;
        }
    }
};

// 启动监控线程
Thread monitorThread = new Thread(monitorTask);
monitorThread.setDaemon(true);
monitorThread.start();

# 5. 最佳实践

# 5.1 资源管理

  • 始终在finally块中归还对象:确保无论是否发生异常,对象都能被归还到池中
  • 及时关闭不再使用的对象池:释放所有资源,避免内存泄漏
  • 验证对象可用性:在对象工厂的validate方法中,严格验证对象的可用性

# 5.2 配置优化

  • 根据实际负载调整池大小:
    • 对于高并发场景,适当增加maxSize和partitionSize
    • 对于低并发场景,适当减小minSize和maxSize
  • 设置合理的等待时间:避免线程长时间阻塞
  • 设置适当的空闲时间:及时回收长时间未使用的对象

# 5.3 线程安全

  • 避免在对象中存储线程相关的状态:对象可能被多个线程复用
  • 确保对象的方法是线程安全的:如果对象不是线程安全的,在使用时需要同步
  • 不要在多个线程之间共享借出的对象:每个线程应该单独借出和归还对象

# 5.4 性能考虑

  • 选择合适的对象工厂:高效的对象创建和验证逻辑可以提高对象池的性能
  • 避免频繁创建和销毁对象:合理设置池大小,减少对象的创建和销毁次数
  • 监控对象池状态:根据实际运行情况调整配置

# 6. 常见问题

# 6.1 对象池满了怎么办?

当对象池满了,并且没有可用的空闲对象时,borrowObject()方法会:

  1. 等待maxWait毫秒
  2. 如果在等待期间有对象被归还,获取并返回该对象
  3. 如果超时仍没有可用对象,抛出异常

# 6.2 如何处理无效对象?

当对象变得无效时(例如数据库连接断开):

  1. 对象工厂的validate方法应该返回false
  2. 对象池会自动销毁无效对象,并创建新对象
  3. 也可以手动调用pool.free(obj)方法销毁无效对象

# 6.3 对象池支持哪些类型的对象?

Hutool的对象池支持任何类型的对象,只要实现了相应的对象工厂。常见的使用场景包括:

  • 数据库连接
  • 网络连接
  • 线程安全的集合对象
  • 复杂的业务对象

# 7. 完整示例

下面是一个完整的对象池使用示例,包括配置、工厂创建、对象池使用和监控:

import cn.hutool.v7.core.pool.ObjectFactory;
import cn.hutool.v7.core.pool.ObjectPool;
import cn.hutool.v7.core.pool.partition.PartitionObjectPool;
import cn.hutool.v7.core.pool.partition.PartitionPoolConfig;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class ObjectPoolExample {
    // 自定义对象:数据库连接包装类
    static class DatabaseConnection {
        private final String connectionId;
        private final long createTime;

        public DatabaseConnection(String connectionId) {
            this.connectionId = connectionId;
            this.createTime = System.currentTimeMillis();
        }

        public String getConnectionId() {
            return connectionId;
        }

        public long getCreateTime() {
            return createTime;
        }

        public boolean isValid() {
            // 简单验证:创建时间小于1小时的连接有效
            return System.currentTimeMillis() - createTime < 3600000;
        }

        public void close() {
            System.out.printf("Closing connection: %s%n", connectionId);
        }
    }

    // 自定义对象工厂
    static class DatabaseConnectionFactory implements ObjectFactory<DatabaseConnection> {
        private int connectionCount = 0;

        @Override
        public DatabaseConnection create() {
            String connectionId = "conn-" + (++connectionCount);
            System.out.printf("Creating connection: %s%n", connectionId);
            return new DatabaseConnection(connectionId);
        }

        @Override
        public boolean validate(DatabaseConnection conn) {
            boolean valid = conn.isValid();
            System.out.printf("Validating connection: %s, result: %b%n", conn.getConnectionId(), valid);
            return valid;
        }

        @Override
        public void destroy(DatabaseConnection conn) {
            conn.close();
        }
    }

    public static void main(String[] args) throws Exception {
        // 创建配置
        PartitionPoolConfig config = new PartitionPoolConfig();
        config.setMinSize(3);
        config.setMaxSize(10);
        config.setMaxWait(5000);
        config.setMaxIdle(60000);
        config.setPartitionSize(2);

        // 创建对象工厂
        DatabaseConnectionFactory factory = new DatabaseConnectionFactory();

        // 创建对象池
        ObjectPool<DatabaseConnection> pool = new PartitionObjectPool<>(config, factory);

        // 启动监控线程
        Thread monitorThread = new Thread(() -> {
            while (true) {
                try {
                    int total = pool.getTotal();
                    int idle = pool.getIdleCount();
                    int active = pool.getActiveCount();
                    System.out.printf("[%s] Pool status: total=%d, idle=%d, active=%d%n",
                        new Date(), total, idle, active);
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        monitorThread.setDaemon(true);
        monitorThread.start();

        // 模拟多个线程使用对象池
        for (int i = 0; i < 5; i++) {
            final int threadId = i;
            new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    DatabaseConnection conn = null;
                    try {
                        // 借出对象
                        conn = pool.borrowObject();
                        System.out.printf("Thread %d borrowed connection: %s%n",
                            threadId, conn.getConnectionId());
                        // 模拟使用对象
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        // 归还对象
                        if (conn != null) {
                            pool.returnObject(conn);
                            System.out.printf("Thread %d returned connection: %s%n",
                                threadId, conn.getConnectionId());
                        }
                    }
                }
            }).start();
        }

        // 等待所有线程完成
        TimeUnit.SECONDS.sleep(10);

        // 关闭对象池
        pool.close();
        Console.log("Object pool closed.");
    }
}

# 8. 总结

Hutool的对象池实现提供了高效、线程安全的对象管理机制,通过分区设计减少了线程竞争,提高了并发性能。使用Hutool的对象池,可以有效降低对象创建成本,提高系统性能和资源利用率。

在使用对象池时,需要注意以下几点:

  1. 合理配置对象池:根据实际负载调整池大小、等待时间等参数
  2. 实现高效的对象工厂:优化对象的创建、验证和销毁逻辑
  3. 正确使用对象池:始终在finally块中归还对象,及时关闭不再使用的对象池
  4. 监控对象池状态:根据实际运行情况调整配置
  5. 确保对象的线程安全:避免在对象中存储线程相关的状态

通过合理使用Hutool的对象池,可以显著提高系统的性能和可靠性,特别是在高并发场景下。

对象池架构设计
反射

← 对象池架构设计 反射→

Theme by Vdoing | Copyright © 2025-2026 Hutool | Apache-2.0
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式