BufferPool 是一个用于管理字节缓冲区(ByteBuffer)的内存池实现,主要目的是减少频繁的内存分配和释放操作,提高内存使用效率。
主要成员变量
- 
totalSize: 内存池总大小
- 
slotSize: 标准槽位大小
- 
free: 当前剩余可用内存大小
- 
slotQueue: 存放可重用的固定大小(slotSize)的 ByteBuffer 队列
- 
waiters: 等待内存分配的线程条件队列
- 
lock: 用于同步控制的锁
核心方法
1. 构造函数 BufferPool(int totalSize, int slotSize)
初始化内存池的总大小和标准槽位大小,并设置初始可用内存为总大小。
2. allocate(int size, long timeout) 方法
申请指定大小的内存缓冲区:
- 
首先检查申请大小是否合法 
- 
如果申请大小正好是 slotSize 且 slotQueue 中有可用缓冲区,直接返回 
- 
如果当前可用内存(包括可释放的固定缓冲区)足够,则分配新内存 
- 
如果内存不足,当前线程进入等待队列,超时或被唤醒后重试 
- 
在 finally 块中确保如果有等待线程且内存可用时唤醒下一个等待线程 
3. deallocate(ByteBuffer byteBuffer) 方法
释放缓冲区:
- 
如果缓冲区大小等于 slotSize,清空并放回 slotQueue 供重用 
- 
否则,直接增加可用内存大小 
- 
如果有等待线程,唤醒一个 
4. freeUp(int size) 私有方法
当需要分配内存但当前空闲内存不足时,尝试从 slotQueue 中释放缓冲区来腾出空间。
设计特点
- 
两种内存管理策略: - 
对于 slotSize 大小的缓冲区:重用机制 
- 
其他大小的缓冲区:直接分配/释放 
 
- 
- 
公平等待: - 使用队列管理等待线程,避免饥饿
 
- 
超时控制: - 支持带超时的内存申请
 
- 
线程安全: - 使用 ReentrantLock 和 Condition 保证线程安全
 
            
            
              java
              
              
            
          
          package com.zsy;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 字节缓冲区内存池实现类
 *
 * <p>本类实现了一个线程安全的字节缓冲区内存池,支持固定大小的槽位分配和释放,
 * 并提供带超时机制的缓冲区申请功能。</p>
 *
 * @author gongxuanzhangmelt@gmail.com
 */
public class BufferPool {
    /**
     * 内存池总容量(字节)
     */
    private final int totalSize;
    /**
     * 每个槽位的大小(字节)
     */
    private final int slotSize;
    /**
     * 当前空闲内存大小(字节)
     */
    private int free;
    /**
     * 可用槽位队列(先进先出)
     */
    private final Deque<ByteBuffer> slotQueue = new ArrayDeque<>();
    /**
     * 等待队列(存储等待内存分配的线程条件)
     */
    private final Deque<Condition> waiters = new ArrayDeque<>();
    /**
     * 可重入锁,用于线程同步
     */
    private final Lock lock = new ReentrantLock();
    /**
     * 构造函数
     *
     * @param totalSize 内存池总容量(字节)
     * @param slotSize 每个槽位的大小(字节)
     * @throws IllegalArgumentException 如果参数不合法(小于等于0)
     */
    public BufferPool(int totalSize, int slotSize) {
        if (totalSize <= 0 || slotSize <= 0) {
            throw new IllegalArgumentException("内存池大小和槽位大小必须大于0");
        }
        this.totalSize = totalSize;
        this.slotSize = slotSize;
        this.free = totalSize;
    }
    /**
     * 申请指定大小的字节缓冲区
     *
     * @param size 请求的缓冲区大小(字节)
     * @param timeout 最大等待时间(毫秒)
     * @return 分配到的ByteBuffer对象
     * @throws InterruptedException 如果线程在等待时被中断
     * @throws RuntimeException 如果请求大小不合法或超时未分配到内存
     */
    public ByteBuffer allocate(int size, long timeout) throws InterruptedException {
        // 方法实现...
        if (size > totalSize || size <= 0) {
            throw new RuntimeException("你的申请容量异常" + size);
        }
        lock.lock();
        try {
            if (size == slotSize && !slotQueue.isEmpty()) {
                return slotQueue.pollFirst();
            }
            if ((free + slotQueue.size() * slotSize) >= size) {
                freeUp(size);
                free -= size;
                return ByteBuffer.allocate(size);
            }
            Condition condition = lock.newCondition();
            waiters.addLast(condition);
            long remainTime = timeout;
            try {
                while (true) {
                    long start = System.currentTimeMillis();
                    boolean wakeup = condition.await(remainTime, TimeUnit.MILLISECONDS);
                    if (!wakeup) {
                        throw new RuntimeException("规定时间内不能申请需要的内存");
                    }
                    if (size == slotSize && !slotQueue.isEmpty()) {
                        return slotQueue.pollFirst();
                    }
                    if ((free + slotQueue.size() * slotSize) >= size) {
                        freeUp(size);
                        free -= size;
                        return ByteBuffer.allocate(size);
                    }
                    remainTime -= System.currentTimeMillis() - start;
                }
            } finally {
                waiters.remove(condition);
            }
        } finally {
            if (!waiters.isEmpty() && !(free == 0 && slotQueue.isEmpty())) {
                waiters.peekFirst().signal();
            }
            lock.unlock();
        }
    }
    /**
     * 释放字节缓冲区到内存池
     *
     * @param byteBuffer 要释放的ByteBuffer对象
     * @throws NullPointerException 如果参数为null
     */
    public void deallocate(ByteBuffer byteBuffer) {
        // 方法实现...
        lock.lock();
        try {
            if (byteBuffer.capacity() == this.slotSize) {
                byteBuffer.clear();
                this.slotQueue.addLast(byteBuffer);
            } else {
                free += byteBuffer.capacity();
            }
            if (!waiters.isEmpty()) {
                waiters.peekFirst().signal();
            }
        } finally {
            lock.unlock();
        }
    }
    /**
     * 内部方法:释放足够的内存以满足请求大小
     *
     * @param size 需要的内存大小
     */
    private void freeUp(int size) {
        // 方法实现...
        while (free < size && !slotQueue.isEmpty()) {
            free += slotQueue.pollFirst().capacity();
        }
    }
}