Handler源码学习(二)Message对象池

Handler源码学习(一)流程
Handler源码学习(二)Message对象池
Handler源码学习(三)MessageQueue入队插队
消息池是全系统共用,上限为50个

private static final int MAX_POOL_SIZE = 50;
// sometimes we store linked lists of these things
/*package*/ Message next;
private static Message sPool;

//假设现在消息池为空,从new message开始,到这个message被取出使用后,准备回收
//准备工作:拿到同步锁,避免线程不安全
//1.next = sPool,因为池中是空的,所以此时sPool其实是null
//2.spool = this,将当前这个message作为池中中下一个应该被复用的对象
//3.sPoolSize ++;将池子中的数量增加一,这个数量依然是全系统共享
void recycleUnchecked() {
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }
//上面已经回收了一个message,在这里来获取message,看看会发生什么
//同样进入同步代码块
//1.判断sPool是否是为空,如果池子为空,就直接new一个message
//上面已经回收过一个message了,这里应该不为空
//m =sPool;把池子里的这个message取出来
//2.sPool = m.next 将池中下一个复用的对象赋值为m.next,但是我们通过上面的代码发现这个是null,先
//不管
//3.将m.next置为空,m.flags = 0 给了一个标记使用中
//4.从池子中减去
public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    return new Message();
}

上面的过程只有一个mesage,详细解释一下sPool和next,将sPool看成一个指针,通过next来将对象组成了一个链表,因为每次只需要从池子里拿一个对象,所以不需要关心池子里具体有多少个对象,而是拿出当前这个sPool所指向的这个对象就可以了,sPool从思路上理解就是通过左右移动来完成复用和回收

Obtain() -- 复用

Handler源码学习(二)Message对象池_第1张图片
MessageObtain(1).jpg

当调用Obtain()的时候让sPool=next,因为第一个message.next就等于第二个message,从图上看相当于sPool这个指针向后移动了一位,随后会将第一个message.next的值置为空
![Uploading MessageRecycle_209561.jpg . . .]

如下图


Handler源码学习(二)Message对象池_第2张图片
MessageObtain(2).jpg

现在这个链表看上去就断了,如果in-use这个message使用完毕了,怎么回到链表中?

recycleUnchecked() -- 回收

再看回收的方法中的代码,next = sPool,将当前sPool所指向的message对象赋值给in-use的next,然后sPool = this,将sPool指向第一个message对象


Handler源码学习(二)Message对象池_第3张图片
MessageRecycle.jpg

这样,就将链表又恢复了~,而且不管是复用还是回收都是保证线程同步的,所以始终会形成一条链式结构

你可能感兴趣的:(Handler源码学习(二)Message对象池)