MessageQueue 用来存放线程消息
Handler 与Looper沟通
Looper 一个线程可以产生一个Looper对象,对消息进行循环
Message 线程消息的载体
ActivityThread --> main() 函数Looper.prepareMainLooper()就是制造出一个looper
sMainThreadHandler = thread.getHandler();
Looper.loop(),启动,让它开始循环
1.Looper me = myLooper();
2.MessageQueue queue
= me
.mQueue
;
3.Message msg
= queue
.next();
4.msg.target.dispatchMessage(msg)
looper就是一个消息处理中心,它负责管理消息队列,负责让消息发出去,msg.target.dispatchMessage(msg)
mCallback
.handleMessage(msg
)
sThreadLocal
.set(new
Looper());
Looper --> prepare() --> sThreadLocal.set(new Looper()) 设置了looper
MessageQueue的底层实现是利用管道和epoll机制来实现的
文件描述符
是内核为了高效管理已被打开的文件所创建的索引,是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符
pipe
管道,使用I/O流操作,Linux 系统中的一种进程间通信机制。简单来说,管道就是一个文件,在管道的两端,分别是两个打开文件的文件描述符。这两个打开文件描述符都是对应同一个文件,其中一个是用来读的,别一个是用来写的,一般的使用方式就是,一个线程通过读文件描述符中来读管道的内容。当管道没有内容时,这个线程就会进入等待状态,而另外一个线程通过写文件描述符来向管道中写入内容。写入内容的时候,如果另一端正有线程正在等待管道中的内容,那么这个线程就会被唤醒
epoll
IO多路复用机制,可以理解为event poll,不同于忙轮询和无差别轮询,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作)
机制
线程在进入循环之前,会在 JNI 创建管道,当消息队列为空时,线程处于空闲等待状态。通过 epoll 机制监听 EPOLLIN 事件,当有新事件进入消息队列时,并且当前线程处于空闲状态,通过向管道写入数据,来唤醒线程
Handler
在Android中负责发送和处理消息,通过它可以实现线程间通信
Thread
Java中进程执行运算的最小单位,资源调度基本单位
HandlerThread
一个继承Thread的类,进行了便利封装
HandlerThread对象start后可以获得其Looper对象,并且使用这个Looper对象实例Handler,之后Handler就可以运行在其他线程中了。
主线程自动创建好了Looper,但是子线程需要自己创建Looper
Looper.prepare();
mHandler
=
new
Handler();
Looper.loop();
初始化Looper 绑定Handler到子线程的Looper对象 开始启动Looper
最后在主线程绑定过的Handler发消息到子线程
不传递 Looper 创建 Handler
Handler handler = new Handler();
不传递 Looper 对象的情况下,在哪个线程创建 Handler 默认获取的就是该线程的 Looper 对象,那么 Handler 的一系列操作都是在该线程进行的。
传递 Looper 创建 Handler
传递 Looper对象 Handler 就直接使用了。所以对于传递 Looper 对象创建 Handler 的情况下,传递的 Looper 是哪个线程的,Handler 绑定的就是该线程
线程局部变量
ThreadLocal诞生的目的是隔离不同线程所使用的变量
ThreadLocal可以用来把实例变量共享成全局变量,让程序中所有的方法都可以访问到该变量。由于存到ThreadLocal的变量都是当前线程本身,其他线程无法访问,存到ThreadLocal中只是为了方便在程序中同一个线程之间传递这个变量(和解决线程安全没有关系)
Handler
用来发送消息,创建时先获取默认或传递来的 Looper 对象,并持有 Looper 对象包含的 MessageQueue发送消息时使用该 MessageQueue 对象来插入消息并把自己封装到具体的 Message 中
Looper
用来为某个线程作消息循环。Looper 持有一个 MessageQueue 对象 mQueue,这样就可以通过循环来获取 MessageQueue 所维护的 Message。如果获取的 MessageQueue 没有消息时,便阻塞在 loop 的queue.next() 中的 nativePollOnce() 方法里,反之则唤醒主线程继续工作,之后便使用 Message 封装的 handler 对象进行处理
MessageQueue
是一个消息队列,它不直接添加消息,而是通过与 Looper 关联的 Handler 对象来添加消息
Message
包含了要传递的数据和信息