底层要点简述
详细的,可以看一下这篇博客给
ThreadLocal
的关键分析Android(Java) | 如何使程序实现线程安全(拓展分析:ThreadLocal、重排序、volatile/final)
- 首先,底层实现了一个线程本地存储,叫
ThreadLocal
区域,
一个主线程以及它对应的所有子线程,共享
同一个ThreadLocal
对象,
这个ThreadLocal对象
中可以说逻辑上维护着一个内存空间
,
这个内存空间
为不同的线程一 一 对应
地维护一套数据副本【t.thread】
,
每一套
数据副本对应着一个线程
(有多少线程
共享这个ThreadLocal对象,ThreadLocal对象就准备多少套数据副本
【createMap(t, value)
】),
每一套数据副本在这里可以具体化为一个Object数组
;
不同线程访问同一个ThreadLocal的get方法,
比如对应线程的Looper,
ThreadLocal的索引值(key)就是ThreadLocal
为每个线程创建的独立的threadLocals实例(ThreadLocal<Looper>对应)
;
value就是不同线程自己的Looper对象;
- 而主线程及其所有子线程都可以开辟自己的
Looper
,
每一个Looper
都要绑定在一个Handler
上,(如下方图1图2)
然后这些个每个单独的Looper
,
都是Looper
对应线程共享的ThreadLocal
中某一个数据副本
中的一个项的value
,
这个项有key
和value
两部分,
value
是刚说的每一个线程对应的Looper
,
然后这个唯一的静态的Looper对象
了关联着一个MessageQueue
,
整个消息机制的工作流程常规表述
首先在需要传递消息的地方,我们构造一个
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()
处理这个消息。
附图
机制中相关元素的数量关系
Thread(线程):负责调度整个消息循环,即消息循环的执行场所。
存在关系:
- 每个Thread(包括主线程、子线程)都可有且只能有一个Looper,可以有多个Handler;
- Looper有一个MessageQueue,可以处理来自多个(绑定同一个Looper)Handler的Message;
- MessageQueue有一组待处理的Message,这些Message可来自不同的Handler;
- Message中记录了负责发送和处理消息的Handler;
一个Message对应一个Handler,
一个Handler可以发送多个Message;- Handler绑定Looper(默认绑定主线程)和MessageQueue;
参考资料:
《Android开发艺术探索》
实用要点总结
- 主线程创建时,会自动创建一个默认的Looper对象,而Looper对象的建立将自动创建一个MessageQueue。其他非主线程,不会自动创建Looper,需要的时候通过prepar函数实现。
- 每一个MessageQueue都不能脱离Looper而存在,
Looper对象的创建是通过prepare函数来实现的。 - 同时每一个Looper对象和一个线程关联。
·通过调用Looper.myLooper()可以获得当前线程的Looper对象,创建一个Looper对象时,会同时创建一个messagequeue对象。 - 除了主线程有默认的Looper,
其他子线程默认是没有MessageQueue对象的,默认不能接受Message。 - 如需要接受,子线程需自己定义 一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。
Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。 - 以上理论详见 —— Android之Message、handler学习
- 相关博客 ——通信之线程间通信(上)-handler
- 子线程也有一套 Message 机制,有它自己的 MessageQueue、Looper、Handler。(可以自己创建) —— 字节跳动面试官:Android 中为什么需要 Handler?
- 创建子线程消息队列系统,推荐使用
HandlerThread
—— Handler系列之创建子线程Handler
public class HandlerThreadActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText("HandlerThreadActivity.class");
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
Handler mHandler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("HandlerThreadActivity.class","uiThread2------"+Thread.currentThread());//子线程
}
};
Log.d("HandlerThreadActivity.class","uiThread1------"+Thread.currentThread());//主线程
mHandler.sendEmptyMessage(1);
}
}