你经常调用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()什么原理吗?相关推荐

  1. 关于在用异步消息处理机制使用Message.Obtain()方法(而非New Message)获得一个Message对象的好处

    类概述 定义一个包含任意类型的描述数据对象,此对象可以发送给Handler.对象包含两个额外的int字段和一个额外的对象字段,这样可以使得在很多情况下不用做分配工作. 尽管Message的构造器是公开 ...

  2. Handler基本使用(二)new Message 、 Handler.obtainMessage和Message.obtain

    通常使用handler发送信息时,会使用下面两种方式 //方法1Message msg = new Message();msg.what = 1;msg.arg1 = 2;msg.arg2 = 3;m ...

  3. C语言handler类作用,Handle的原理(Looper、Handler、Message三者关系)

    转载请注明出处:http://blog.csdn.net/lowprofile_coding/article/details/72580044 介绍 前面的内容对Handler做了介绍,也讲解了如何使 ...

  4. Handle的原理(Looper、Handler、Message三者关系)

    转载请注明出处:http://blog.csdn.net/lowprofile_coding/article/details/72580044 介绍 前面的内容对Handler做了介绍,也讲解了如何使 ...

  5. Message中obtain()与recycle()

    Message中obtain()与recycle() 原文:链接 在obtain的所有重载方法中,第一行都是Message m = obtain();,即调用空参的方法. 先来看一下这个空参方法 pu ...

  6. Android刷新机制-View绘制原理

    Android刷新机制-View绘制原理 Android刷新机制-SurfaceFlinger原理 Android刷新机制-Choreographer原理 一.概述 本文将从startActivity ...

  7. android handler的机制和原理_一文搞懂handler:彻底明白Android消息机制的原理及源码

    提起Android消息机制,想必都不陌生.其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行.本篇文章将由浅入深解析Android消息机制的运 ...

  8. Android 插件化原理学习 —— Hook 机制之动态代理

    前言 为了实现 App 的快速迭代更新,基于 H5 Hybrid 的解决方案有很多,由于 webview 本身的性能问题,也随之出现了很多基于 JS 引擎实现的原生渲染的方案,例如 React Nat ...

  9. Android Handler与Looper原理简析

    一直感觉自己简直就是一个弱智,最近越来越感觉是这样了,真的希望自己有一天能够认同自己,认同自己. 本文转载于:https://juejin.im/post/59083d7fda2f60005d14ef ...

  10. Android Handler的原理

    简介 在 Android 中,只有主线程才能操作 UI,但是主线程不能进行耗时操作,否则会阻塞线程,产生 ANR 异常,所以常常把耗时操作放到其它子线程进行.如果在子线程中需要更新 UI,一般是通过 ...

最新文章

  1. 前端面试查漏补缺--(一) 防抖和节流
  2. 打包解决方案后,安装时提示只能在IIS5.1以上运行解决方法
  3. Mysql Explain 详解
  4. [ Python ] PIL
  5. 代码UITableView点击cell跳转
  6. 单链表的整表创建以及整表删除
  7. java监听网络连接_Android RxJava 之网络链接监听示范
  8. CentOS6离线升级CentOS7
  9. java延迟队列,java高级面试笔试题
  10. 关于电脑程序员职务 用英语怎么表达
  11. java语言是那年_Java语言是在()年正式推出的_学小易找答案
  12. NOIP2017 D2T1 奶酪
  13. 20160801java学习重点:函数
  14. JDK自带的native2ascii工具完全揭密
  15. MATLAB基本语法速成
  16. 日志管理系统,多种方式总结
  17. 简述java工厂模式详解_JAVA 设计模式之 工厂模式详解
  18. 零基础入门网络,静态LACP链路捆绑详解,带宽扩容,链路冗余备份
  19. pylint高频警告错误的原因及处理建议
  20. 详解ORACLE数据库的分区表

热门文章

  1. win10网络显示已连接到服务器异常,w10 网络连接配置异常如何修复
  2. 迷你世界服务器为什么在维护,迷你世界为什么进不去迷你世界进不去怎么办
  3. w10系统打不开服务器共享打印机,共享打印机拒绝访问怎么办?Win10打印机无法共享的解决办法...
  4. 小程序怎么接入第三方客服工具?
  5. SQL 事务(Tran | Transation)与 Try...Catch 的使用
  6. R、冗余分析(RDA)、ggplot2、置信椭圆
  7. android 图片 3d 动画,DEMO:transition3d、运用动画实现图片3d翻转效果
  8. 计算机键盘上的句号键在哪,电脑键盘句号是哪个键
  9. Vue.js实现文章评论和回复评论功能
  10. WPS自动生成目录,目录里显示图片如何解决