美文网首页
HandlerThread

HandlerThread

作者: Doctor_Xu | 来源:发表于2020-07-03 18:02 被阅读0次

    简介

    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执行完毕退出。

    相关文章

      网友评论

          本文标题:HandlerThread

          本文链接:https://www.haomeiwen.com/subject/kovsqktx.html