你知道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?

Handler 的 Message 实例怎么创建,为什么不是直接 new?

Handler系列—Message对象的获取机制

详解Android消息机制之Message

Handler源码分析

腾讯面试官问:你知道什么是AOP吗?AOP与OOP有什么区别,谈谈AOP的原理是什么?