今天偶然发现support包下内置了通用型对象池
android.support.v4.util.Pool
对象池的设定很简单
/**
* Interface for managing a pool of objects.
*
* @param <T> The pooled type.
*/
public static interface Pool<T> {
/**
* @return An instance from the pool if such, null otherwise.
*/
public T acquire();
/**
* Release an instance to the pool.
*
* @param instance The instance to release.
* @return Whether the instance was put in the pool.
*
* @throws IllegalStateException If the instance is already in the pool.
*/
public boolean release(T instance);
}
acquire()负责获取对象 release(T)负责释放对象。同时内置实现了2类对象池
- 同步对象池
SynchronizedPool - 非同步对象池
SimplePool实质区别在于同步对象池中使用了同步块
//...
private final Object mLock = new Object();
//...
@Override
public T acquire() {
synchronized (mLock) {
return super.acquire();
}
}
@Override
public boolean release(T element) {
synchronized (mLock) {
return super.release(element);
}
}
在内部实现中,对象池采用数组存储对象
private final Object[] mPool;
- 初始化时设定对象池大小,由于对象池不存在类似采用数组实现的结构如ArrayList的含有扩容的操作,因此不需要考虑在此的性能问题
- 数据获取/释放均在数组尾部进行操作,实质将该数组作为堆栈使用
总结
support包中的Pool的设计可谓是轻巧,精密。但仍有较大区别与一般的通用型对象池。
关于对象池,一般使用于创建/销毁对象存在较大性能的情况下类似缓存的一种解决方案。在现代JVM上,小对象的创建和回收动作是非常廉价,不一定具有入对象池的资格。
实际上,可以在Pool的基础做些改进
- 增加阻塞机制--对象的获取,存在一定概率对象池中已没有可用对象,这时需要一个相应的阻塞策略(阻塞队列)
- 增加对象过期机制,没有过期失效机制,可能会存在
沉底对象--永远不会被使用,占据空间 - 建立线程池,将对象的获取,释放置于I/O线程由线程池统一管理
- 提供安全关闭对象池方法,确保无内存泄漏问题
- new Object()锁可考虑更换为
private final byte[] mLock = new byte[0];
生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码