Java对象池

前端时间,因为项目的需要对Toast进行一些封装,过程中涉及到一个改进性能问题,在同事的启发下,看Android的Message类,其中就用到了对象池的操作.虽然只是几段代码,但是的确是研究了很久才弄明白怎么操作,现在分享一下.

先看Message源代码:

 1     private static final Object sPoolSync = new Object();
 2     private static Message sPool;
 3     private static int sPoolSize = 0;
 4     private static final int MAX_POOL_SIZE = 10;
 5 
 6     /**
 7      * Return a new Message instance from the global pool. Allows us to
 8      * avoid allocating new objects in many cases.
 9      */
10     public static Message obtain() {
11         synchronized (sPoolSync) {
12             if (sPool != null) {
13                 Message m = sPool;
14                 sPool = m.next;
15                 m.next = null;
16                 sPoolSize--;
17                 return m;
18             }
19         }
20         return new Message();
21     }
22 
23     /**
24      * Return a Message instance to the global pool.  You MUST NOT touch
25      * the Message after calling this function -- it has effectively been
26      * freed.
27      */
28     public void recycle() {
29         clearForRecycle();
30         synchronized (sPoolSync) {
31             if (sPoolSize < MAX_POOL_SIZE) {
32                 next = sPool;
33                 sPool = this;
34                 sPoolSize++;
35             }
36         }
37     }

在这里,获取的对象并不是直接New出来的,而是通过obtain()方法获取的,当然在这个方法里面会有New的情况.

看过程:

  1. 如果一开始sPool为空的话,就什么也不说了,直接New一个对象;
  2. 如果对这个对象的需求强烈的话,还会New出几个对象来,这个过程中sPool一直为空;
  3. 一旦之前New出来的对象中的某一个(这里简称"b对象")被使用完了,那么需要手工调一下recycle()方法(b.recycle()),一旦这个方法被调用,则会完成以下操作;
    将之前挂在sPool引用下的对象赋值
    给c.next(c.next=pool),然后将c对象自己挂在sPool引用下面(sPool=this).
    这样,每有一个对象调用了recycle()方法,sPool引用下的对象就会像条绳子一样越来越长.
  4. 一旦sPool不为空,则说明之前已经有对象调用过recycle()方法,此时就不需要New对象出来,而是将sPool引用下的对象拿出一个来用.即可;
    (1)将sPool引用下的对象拿出来.(Message m = sPool;)
    (2)将拿出来的对象的next属性下的对象挂在sPool引用下.(sPool = m.next)
    (3)将拿出来的对象的next引用清除.(m.next = null)

刚开始看的时候不明白对象的池在哪里,后来终于明白了,其实主要就是两个引用,一个是静态的sPool,一个是对象的属性next.sPool就像一个挂在树上固定的大钩子,对象就是挂在钩子上的箩筐,而每一个箩筐上还有一个小钩子(next)可以钩其他箩筐,就这样一个钩一个.
(1)存储对象的过程就像往那一列箩筐上在挂一个新箩筐(但不能往最下面的箩筐上挂,只能往那个钩子上挂),那就只能把之前挂在大钩子上的一列箩筐先挂在新的箩筐的小钩子,然后在把新的箩筐挂在大钩子上,这样存储的过程就完成了.
(2)拿出对象的过程就是先把这列箩筐从大钩子上摘下来,然后把最上面上的箩筐的小钩子上的那列箩筐挂到大钩子上,最后还要确保那出来的这个箩筐的小钩子上已经没有挂着别的箩筐了.这样就完成了.

posted @ 2013-03-20 13:44  Xiao.Yang  阅读(1342)  评论(1编辑  收藏  举报