题目
设计一个支持泛型的对象池(Object Pool)
信息
- 类型:问答
- 难度:⭐⭐
考点
泛型类设计,类型边界限定,通配符应用,线程安全
快速回答
实现一个线程安全的泛型对象池,需满足:
- 使用泛型类
ObjectPool<T>管理任意类型对象 - 类型
T必须实现AutoCloseable接口 - 提供
borrowObject()和returnObject(T obj)方法 - 使用通配符实现安全的对象回收校验
- 确保线程安全并避免资源泄漏
问题背景
对象池是性能优化中常用的技术,通过复用昂贵资源(如数据库连接)减少创建开销。本题要求用泛型实现通用对象池,考察泛型综合应用能力。
核心实现
1. 泛型类定义与类型边界
public class ObjectPool<T extends AutoCloseable> {
private final Queue<T> pool = new LinkedList<>();
private final Supplier<T> objectFactory;
public ObjectPool(Supplier<T> objectFactory) {
this.objectFactory = objectFactory;
}
}关键点:
<T extends AutoCloseable>确保池中对象可被关闭,防止资源泄漏- 使用
Supplier<T>解耦对象创建逻辑
2. 对象借出与归还方法
// 借出对象
public synchronized T borrowObject() {
if (pool.isEmpty()) {
return objectFactory.get();
}
return pool.poll();
}
// 归还对象(使用通配符校验)
public synchronized void returnObject(T obj) {
if (obj != null) {
pool.offer(obj);
}
}
// 安全关闭方法
public void closePool() {
for (T obj : pool) {
try {
obj.close();
} catch (Exception e) { /* 处理异常 */ }
}
pool.clear();
}3. 通配符高级应用
若需实现跨类型安全回收(如子类对象归还父类池):
public void safeReturn(ObjectPool<? super T> pool, T obj) {
pool.returnObject(obj); // 使用下界通配符确保类型安全
}最佳实践
- 资源管理: 通过
AutoCloseable边界强制实现关闭逻辑 - 线程安全: 使用
synchronized或ReentrantLock保护共享队列 - 对象生命周期: 在
closePool()中统一释放资源 - 防御性编程: 归还时进行非空校验
常见错误
- 类型擦除问题: 运行时无法获取泛型具体类型,需通过构造函数传入
Class<T>或Supplier<T> - 线程安全问题: 未同步共享队列导致竞态条件
- 资源泄漏: 未实现
closePool()或忽略AutoCloseable调用 - 通配符误用: 错误使用上界通配符(
? extends T)导致归还失败
扩展知识
- 通配符对比:
<? super T>(下界):允许写入T及其父类(PECS原则中的Consumer)<? extends T>(上界):允许读取为T(Producer)
- 性能优化: 可使用
BlockingQueue实现阻塞获取 - 对象状态重置: 在归还时调用
reset()方法(需额外接口约束)
完整代码示例
import java.util.*;
import java.util.function.Supplier;
public class ObjectPool<T extends AutoCloseable> {
private final Queue<T> pool = new LinkedList<>();
private final Supplier<T> objectFactory;
public ObjectPool(Supplier<T> objectFactory) {
this.objectFactory = objectFactory;
}
public synchronized T borrowObject() {
return pool.isEmpty() ? objectFactory.get() : pool.poll();
}
public synchronized void returnObject(T obj) {
if (obj != null) pool.offer(obj);
}
public synchronized void closePool() throws Exception {
for (T obj : pool) {
obj.close();
}
pool.clear();
}
// 跨类型安全归还示例
public static <E extends AutoCloseable> void
safeReturn(ObjectPool<? super E> pool, E obj) {
pool.returnObject(obj);
}
}
// 使用示例
class DatabaseConnection implements AutoCloseable {
public void executeQuery() { /* ... */ }
@Override public void close() { /* 释放连接 */ }
}
public class Main {
public static void main(String[] args) {
ObjectPool<DatabaseConnection> pool =
new ObjectPool<>(DatabaseConnection::new);
DatabaseConnection conn = pool.borrowObject();
try {
conn.executeQuery();
} finally {
pool.returnObject(conn);
}
}
}