HandlerThread

2020-07-03  本文已影响0人  Doctor_Xu

简介

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;
    }
  1. 为什么执行完Looper.prepare()后就可以使用Looper.myLooper()实例化mLooper对象了呢?
    Looper类中有一个ThreadLocal<Looper>对象,ThreadLocal和当前线程绑定,并且存储的数据对象为Looper对象,因此使用ThreadLocal保存了当前线程的Looper的对象,也即做到了:Looper和当前线程绑定,实例化了当前线程的Looper对象
  2. 为什么在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对象

  1. onLooperPrepared()函数
    空函数,主要是用于继承HandlerThread的类做一些自定义的业务
  2. 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执行完毕退出。

上一篇下一篇

猜你喜欢

热点阅读