Support包下的对象池

336 阅读2分钟

今天偶然发现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行操作码