小站
小站
文章目录
  1. Obtain() – 复用
  2. recycleUnchecked() – 回收

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() – 复用

MessageObtain(1).jpg

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

如下图
MessageObtain(2).jpg

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

recycleUnchecked() – 回收

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

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

支持一下
如果对你有帮助,也可以支持下小站