你知道Message.obtain()什么原理吗?
Posted 凌日新
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你知道Message.obtain()什么原理吗?相关的知识,希望对你有一定的参考价值。
你经常调用Message.obtain()来复用一个Message对象吧?有看过内部实现吗?
我…[污]
Message.obtain()可以返回一个可循环使用的Message对象,那思考以下几个问题:
1、Message.obtain 返回的Message是哪来的?
2、Message.obtain 返回的对象是怎么存储的?
3、可循环使用的Message对象 和 普通Message对象有什么区别?
4、Message对象的存储池配置了多大?超过上限会弹性扩充吗?
解题[舔屏]:
1、 Message.obtain 返回的Message是哪来的?
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();
源码一看,我擦 真简单,要不就是 sPool对象,要不就是new Message()。
new就不说了,sPool是个啥?
private static Message sPool;
它也是个Message?,那m.next是?
// sometimes we store linked lists of these things
@UnsupportedAppUsage
/package/ Message next;
没错,自链表实现,要不就是new出来的,要不就去取 上次储的sPool。
2、Message.obtain 返回的对象是怎么存储的?
我们刚看到,sPool主要是别人储起来的,那是谁存起来的呢?追代码。
/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
@UnsupportedAppUsage
void recycleUnchecked()
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync)
if (sPoolSize < MAX_POOL_SIZE)
next = sPool;
sPool = this; //这里赋的值
sPoolSize++;
soga,原来是这里,那这破方法是,内部方法,谁调的呢?
/**
* Return a Message instance to the global pool.
*
* You MUST NOT touch the Message after calling this function because it has
* effectively been freed. It is an error to recycle a message that is currently
* enqueued or that is in the process of being delivered to a Handler.
*
*/
public void recycle()
if (isInUse())
if (gCheckRecycle)
throw new IllegalStateException("This message cannot be recycled because it "
+ “is still in use.”);
return;
recycleUnchecked();
soga,原来有一个 open 的recycle,到这里 貌似 串起来了,我们自己new,然后自己recycle,然后自己obtain,完事!
3、可循环使用的Message对象 和 普通Message对象有什么区别?
看了这么多源码,可以确定,它们是一回事。
4、Message对象的存储池配置了多大?超过上限会弹性扩充吗?
这是个好问题,如果我们创建一堆的Message,都调用recycle,那这链表不就无限长了?Message就回收不了了,总有一天会oom。
那主要看回收部份。
synchronized (sPoolSync)
if (sPoolSize < MAX_POOL_SIZE)
next = sPool;
sPool = this;
sPoolSize++;
哈,有个上限 MAX_POOL_SIZE,那定义了多少?
public static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
看到了,50,也就是说,缓存了50个Messge,我就不再缓存了。所以没有 弹性扩充 的问题。
别走客官,如果…
1、这玩意使用到了对象锁,在多线程竞争中,必然效率低下,你还有没有更好的Message循环利用方式,可以代替synchronized呢?
2、这种循环利用方法,你叫它什么设计模式呢?
3、我擦,我之前只用Message.Obtain(),从来不调message.recycle()。(逃~)
欢迎留言、分享、转发,一键三连。
三连的人很酷酷酷酷酷酷~~[坏笑]
以上是关于你知道Message.obtain()什么原理吗?的主要内容,如果未能解决你的问题,请参考以下文章
Handler 的 Message 实例怎么获得?为什么不是直接 new?