底层要点简述
- 首先,底层实现了一个线程本地存储,叫
ThreadLocal
区域,
一个主线程以及它对应的所有子线程,共享
同一个 ThreadLocal
对象,
这个ThreadLocal对象
中可以说逻辑上维护着一个内存空间
,
这个内存空间
为不同的线程一 一 对应
地维护一套数据副本
,每一套
数据副本对应着一个线程
(有多少线程
共享这个ThreadLocal对象,ThreadLocal对象就准备多少套数据副本
),
每一套数据副本在这里可以具体化为一个Object数组
;
不同线程访问同一个ThreadLocal的get方法,
ThreadLocal内部会从(数据副本里)各自的线程中取出一个数组,
然后再从数组中根据当前ThreadLocal的索引去查找对应的value值。
比如对应线程的Looper,
ThreadLocal的索引值(key)就是唯一的静态的Looper对象(ThreadLocal<Looper>对应)
;
value就是不同线程自己的Looper对象;
- 而主线程及其所有子线程都可以开辟自己的
Looper
,
每一个Looper
都要绑定在一个Handler
上,(如下方图1图2)
然后这些个每个单独的Looper
,
都是Looper
对应线程共享的ThreadLocal
中某一个数据副本
中的一个项的value
,
这个项有key
和value
两部分,value
是刚说的每一个线程对应的Looper
,
而key
则是存放在ThreadLocal
中一个唯一的静态的Looper对象(ThreadLocal<Looper>)
了,(如下方图3)
然后这个唯一的静态的Looper对象
了关联着一个MessageQueue
,
- 也就是说,
所有线程的Looper
都映射到同一个Looper
上,
所有线程的Looper
中关联的MessageQueue
也是映射到对应的同一个MessageQueue
上;(如下方图1图2)
整个消息机制的工作流程常规表述
- 首先在需要传递消息的地方,我们构造一个
Message(消息)
对象,
此时Message
中会有自己的一个ID
,
然后我们把需要传递的数据设置在这个Message
里面,
借助Handler
的sendMessage()
方法将Message
传递到MessageQueue
中,
此时MessageQueue
通过调用MessageQueue.enqueueMessage()
向MessageQueue
自身中添加这条发送过来的Message
;
MessageQueue(消息队列)
中存放着诸多相关联的Handler
发送过来的Message
,
其内部通过单链表
的数据结构来维护消息列表,
等待Looper
的抽取。
Looper(消息泵)
通过Looper.loop()
不断轮询MessageQueue
,
调用MessageQueue.next()
,从MessageQueue
中抽取队头的Message
,
接着调用这个Message
对应的Handler
的dispatchMessage()
,
将该Message
传递分发给对应的Handler
,
- 目标
Handler
收到Message
后调用handlerMessage()
处理这个消息。
可以看一下这篇博客给ThreadLocal的关键分析Android(Java) | 如何使程序实现线程安全(拓展分析:ThreadLocal、重排序、volatile/final)
附图
Thread(线程):负责调度整个消息循环,即消息循环的执行场所。
存在关系:
- 一个Thread只能有一个Looper,可以有多个Handler;
- Looper有一个MessageQueue,可以处理来自多个Handler的Message;
- MessageQueue有一组待处理的Message,这些Message可来自不同的Handler;
- Message中记录了负责发送和处理消息的Handler;
- Handler中有Looper和MessageQueue;