Android对象池

对象池以及其在Android中的应用。

Object pool模式

如果你对object pool模式还不太了解的话,可以先
看看这里

简单总结一下,对象池可以看做一种空间换时间的策略。可以看作是减少GC压力的首选方法,同时也是最简单的方法。在下面两种分配模式下,可以选择使用对象池:

  • 对象以固定的速度不断地分配,垃圾收集时间逐步增加,内存使用率随之增大;
  • 对象分配存在爆发期,而每次爆发都会导致系统迟滞,并伴有明显的GC中断。

双刃剑

以前写作文的时候,尤其是英语作文的时候,经常会说一个事物都会有它的两面性 :), 对象池也不例外,来看看它的优缺点:

Pros:

  • 由于我们不再频繁的或者突然大量的创建新对象,所以其降低了heap使用内存的突然抖动。
  • 减少了GC导致的performance的退化。
  • 对于实时性要求高的应用,或者系统资源紧张的情况有很大的帮助。

Cons:

  • 可能会引入并发相关的bug。
  • 因为dirty ojbect的存在,也可能会引入相应的bug。

正是基于此,我们在使用对象池的时候一定要慎重,一个稳妥的方法是在使用之前先测量一下你的应用performance,看看其运行速度到底是多块,然后采用对象池后再次测量,看是否有提高。如果提高了,很好,可以使用!否则的话就不需要多此一举了。

当你决定要采用对象池的时候,一定要加强测试你的程序,尤其是关于并发的方面的unit test要多做,从而避免引入相关的bug。

Android中对象池的应用

Android平台已经帮我们实现好了对象池,常用的是SynchronizedPool。下面是个例子。假设你的应用会频繁的大量的需要创建某个类的对象,那么我们就可以将该类改造成支持对象池模式,代码如下:

public class MyPooledClass {

     private static final SynchronizedPool<MyPooledClass> sPool =
         new SynchronizedPool(10);

     public static MyPooledClass obtain() {
         MyPooledClass instance = sPool.acquire();
         return (instance != null) ? instance : new MyPooledClass();
     }

     public void recycle() {
          // Clear state if needed.
          sPool.release(this);
     }

     . . .
 }

可以看到实现起来非常简单,只需要在类内部创建一个SynchronizedPool,然后提供obtain和recycle接口即可。

当想创建MyPooledClass的对象的时候,我们不再使用:

MyPooledClass myObject = new MyPooledClass();

而是调用:

MyPooledClass myObject = MyPooledClass.obtain();

当该对象不再使用的时候,记得要将其释放回对象池,否则对象池被用完后,以后每次再去obtain的话就会导致创建一个新对象,这样的话对象池就不再有任何作用。

myObject.recycle();