侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

设计一个支持泛型的对象池(Object Pool)

2025-12-13 / 0 评论 / 4 阅读

题目

设计一个支持泛型的对象池(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 边界强制实现关闭逻辑
  • 线程安全: 使用 synchronizedReentrantLock 保护共享队列
  • 对象生命周期: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);
        }
    }
}