HandlerThread
简介
HandlerThread继承于Thread类,因此它本身就是一个Thread,有Thread的属性和方法,它内部维护了Looper和Handler属性,因此可以用于处理消息循环。
HandlerThread初始化时,直接调用的父类的初始化函数并设置了Priority属性,其实就是实例化了一个线程对象,一切业务都在HandlerThread的run()方法中。
HandlerThread线程运行
当调用HandlerThread.start()方法后,自动执行run()方法,
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
- 为什么执行完Looper.prepare()后就可以使用Looper.myLooper()实例化mLooper对象了呢?
Looper类中有一个ThreadLocal<Looper>对象,ThreadLocal和当前线程绑定,并且存储的数据对象为Looper对象,因此使用ThreadLocal保存了当前线程的Looper的对象,也即做到了:Looper和当前线程绑定,实例化了当前线程的Looper对象 - 为什么在run方法中使用mLooper = Looper.myLooper()要用线程同步
就是为了保证在执行getLooper()时,能够获取到Looper对象
/**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason isAlive() returns false, this method will return null. If this thread
* has been started, this method will block until the looper has been initialized.
* @return The looper.
*/
在调用getLooper()函数时,如果线程已经alive和myLooper对象是null,则阻塞当前调用,等待run方法中执行完了Looper.myLooper()并赋值给myLooper对象,随后执行notifyAll唤醒被阻塞的线程,然后getLooper()函数回到被阻塞的地方继续执行,返回myLooper对象
- onLooperPrepared()函数
空函数,主要是用于继承HandlerThread的类做一些自定义的业务 - Looper.loop()函数
一段代码执行完成后,也即run()方法执行完成后,Thread会退出,可是在执行完Looper.loop()函数后,HandlerThread并没有退出,而是可以处理消息,这是因为:Looper.loop()是一个无限循环函数
public static void loop() {
......
for (;;) {
Message msg = queue.next(); // might block *此处会阻塞,直到获取到消息,null消息也是消息*
if (msg == null) {
// No message indicates that the message queue is quitting.
*只有获取的消息为null时,才会退出消息循环,只有调用quit()或quitSafely()函数时,获取的msg对象才为null*
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
......
}
}
这也就解释了为什么HandlerThread的run()方法不会执行完成,HandlerThread线程不会退出:因为Looper中一直阻塞在读取和处理消息,只有当获取的消息对象为null时,才会退出,此时HandlerThread这个Thread执行完毕退出。