对象池模式通过复用对象减少创建和销毁开销,适用于数据库连接、线程等高成本对象;其核心是预先创建对象并放入池中,使用时获取、用后归还并重置状态,通过concurrentlinkedqueue实现线程安全的获取与归还机制,配合supplier提高通用性,且需注意池大小控制、空闲回收与对象泄漏问题,实际开发中推荐使用apache commons pool等成熟工具而非手动实现,最终在性能提升与资源管理间取得平衡。

对象池模式是一种设计模式,用于管理对象的创建和复用,避免频繁创建和销毁对象带来的性能开销。它特别适用于创建成本高、使用频繁但生命周期短的对象,比如数据库连接、线程、网络连接、游戏中的子弹或粒子效果等。
实现对象池的核心思想是:预先创建一批对象放入“池”中,使用时从池中获取,用完后归还,而不是直接销毁。
下面是如何实现一个基本的对象池模式的步骤和要点:
一、定义对象池接口或基类
为了统一管理,可以先定义一个通用的接口或基类,表示可被池化管理的对象。
public interface PooledObject {
void reset(); // 归还时重置状态
}reset()方法用于在对象归还池中时,清除其内部状态,确保下次使用时是“干净”的。
二、实现具体的可池化对象
以一个简单的“连接”对象为例:
public class Connection implements PooledObject {
private String data;
public void setData(String data) {
this.data = data;
}
public String getData() {
return data;
}
@Override
public void reset() {
this.data = null; // 清理状态
}
@Override
public String toString() {
return "Connection{" + "data='" + data + '\'' + '}';
}
}三、实现对象池管理器
对象池的核心是管理空闲对象的集合,通常使用栈或队列来存储可用对象。
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Supplier; public class ObjectPool{ private final ConcurrentLinkedQueue pool; private final Supplier creator; public ObjectPool(Supplier creator, int initialSize) { this.creator = creator; this.pool = new ConcurrentLinkedQueue<>(); // 预先创建一批对象 for (int i = 0; i < initialSize; i++) { pool.offer(creator.get()); } } // 获取对象 public T acquire() { T obj = pool.poll(); if (obj == null) { // 池空了,创建新对象(可配置是否允许扩容) obj = creator.get(); } return obj; } // 归还对象 public void release(T obj) { if (obj != null) { obj.reset(); // 重置状态 pool.offer(obj); } } }
说明:
- 使用
ConcurrentLinkedQueue
保证线程安全。 Supplier
用于创建新对象,提高通用性。acquire()
从池中取出对象,若池空可选择新建。release()
归还对象前调用reset()
清理状态。
四、使用示例
public class Main {
public static void main(String[] args) {
ObjectPool pool = new ObjectPool<>(
Connection::new, // 创建方式
5 // 初始数量
);
// 获取对象
Connection conn1 = pool.acquire();
conn1.setData("Request 1");
Connection conn2 = pool.acquire();
conn2.setData("Request 2");
System.out.println(conn1);
System.out.println(conn2);
// 使用完归还
pool.release(conn1);
pool.release(conn2);
// 再次获取,可能是之前归还的对象
Connection conn3 = pool.acquire();
System.out.println("Reused: " + conn3); // 可能是 conn1 或 conn2
}
} 五、优化与注意事项
-
线程安全:如果多线程使用,必须保证池的线程安全(上面用了
ConcurrentLinkedQueue
)。 - 池大小控制:可限制最大对象数,避免内存溢出。超过时阻塞或抛异常。
- 超时与空闲回收:长时间未使用的对象可被销毁,节省内存。
- 监控与统计:记录获取/归还次数、等待时间等,便于调优。
-
避免对象泄漏:确保每次
acquire
后最终都会release
,可用 try-finally 或装饰器模式保障。
六、实际应用中的成熟工具
在实际项目中,通常不会手动实现,而是使用成熟的对象池库:
- Apache Commons Pool:Java 中最常用的对象池库,功能完整。
- HikariCP:高性能数据库连接池,内部也用了池化思想。
- Netty 的 Recycler:用于池化 ByteBuf 等对象,极致性能优化。
例如使用 Commons Pool:
org.apache.commons commons-pool2 2.11.1
然后继承
BasePooledObjectFactory并配合
GenericObjectPool使用。
对象池模式的关键在于:减少对象创建销毁的开销,通过复用提升性能。但也要注意,不是所有对象都适合池化——只有创建代价高、使用频繁的对象才值得。
基本上就这些。不复杂,但容易忽略状态重置和线程安全问题。











