Android应用开发Android 多线程之HandlerThread简介
白羽 2019-03-04 来源 :网络 阅读 161 评论 0

摘要:本文将带你了解Android应用开发Android 多线程之HandlerThread介绍,希望本文对大家学Android有所帮助。

    本文将带你了解Android应用开发Android 多线程之HandlerThread介绍,希望本文对大家学Android有所帮助。



Android应用开发Android 多线程之HandlerThread简介


一、什么是HandlerThread及特点
      HandlerThread本质就是一个Thread,在内部建立了消息队列机制(Looper、MessageQueue),具有消息循环的线程。
   
    特点
    HandlerThread本质上一个线程类,它继承了Thread HandlerThread与自己的内部Looper对象,可以进行loop循环   通过获取looper对象传递给Handler对象,并可以在Handler的handleMessage方法中执行异步任务   与线程池重并发不同,handlerThread是一个串行队列,背后只有一个线程   优点就是不会堵塞,减少对信性能的消耗,缺点是不能同时进行多任务处理,需要等待处理,效率较低。
    二、HandlerThread使用方法
    1.创建HandlerThread线程,并在构造方法内传入线程名称,可以是任意字符串
   
 
    HandlerThread mHandlerThread = new HandlerThread(Handler_Thread);
    2.启动线程
   

    mHandlerThread.start();
    3.创建异步Handler对象,并构建Callback消息循环机制
   

       mchildHandler = new   Handler(mHandlerThread.getLooper(), new Handler.Callback() {
                @Override
                public boolean   handleMessage(Message msg) {
     
                      //子线程内运行,此处不能更新UI
                    Log.d(TAG,   handleMessage: +msg.what+ 线程名:+Thread.currentThread().getName());
     
    //                mTvContent.setText(String.valueOf(msg.what));
                      //主线程Hanlder,发送消息通知更新UI
                      mUIHandler.sendMessage(msg);
     
                    return false;
                }
            });
    以上步骤3构建一个完整异步Handler,将HandlerThread的Looper对接和Callback接口类作为参数传递到异步   mchildHandler,这样当前的mchildHandler对象就拥有HandlerThread的Looper对象,由于HandlerThread本身是异步线程,故Looper也绑定到异步线程中,所以handleMessage方法是处理异步耗时任务,当处理状态发生改变,需要UI线程的Handler发送消息通知更新UI。
   

      mchildHandler = new   Handler(mHandlerThread.getLooper(), new Handler.Callback() {
                @Override
                public boolean   handleMessage(Message msg) {
     
                      //子线程内运行,此处不能更新UI
                    Log.d(TAG,   handleMessage: +msg.what+ 线程名:+Thread.currentThread().getName());
     
    //                  mTvContent.setText(String.valueOf(msg.what));
                      //主线程Hanlder,通知主线程更新
                    Message message =   Message.obtain();
                      message.what=msg.what;
                      mUIHandler.sendMessage(message);
     
                    return false;
                }
            });
    模拟触发异步线程
   

    for (int i = 0; i <= 10; i++) {
                        Message obtain =   Message.obtain();
                        obtain.what =   i;
                          mchildHandler.sendMessageAtTime(obtain,1000);
                    }
    源码分析>三、HandlerThread源码分析
    首先我们从构造函数开始:

    public class HandlerThread extends Thread {
        //线程优先级
        int mPriority;
        int mTid = -1;
        //当前线程所持有的Looper对象
        Looper mLooper;
        private @Nullable Handler   mHandler;
     
        public HandlerThread(String name)   {
            super(name);
            mPriority =   Process.THREAD_PRIORITY_DEFAULT;
        }
     
        /**
         * Constructs a   HandlerThread.
         * @param name
         * @param priority The priority   to run the thread at. The value supplied must be from
         * {@link android.os.Process} and   not from java.lang.Thread.
         */
        public HandlerThread(String name,   int priority) {
            super(name);
            mPriority = priority;
        }
      从源码可以看出HandlerThread是继承于Thread,本质上是一个线程,构造方法需要传入两个参数,一个是name指的是线程名称,一个是priority指的是线程的优先级,当创建了HandlerThread对象并开启线程start方法后,run方法就会马上执行,接下来看看run方法:


    /**
        * Call back method that can be   explicitly overridden if needed to execute some
        * setup before Looper   loops.
        */
       protected void onLooperPrepared()   {
       }
     
       @Override
       public void run() {
           mTid = Process.myTid();
           //在当前线程初始化一个Looper对象
           Looper.prepare();
           synchronized (this) {
                 //把初始化的Looper对象赋值给HandlerThread的内部mLooper
               mLooper =   Looper.myLooper();
               //唤醒等待线程
               notifyAll();
           }
             Process.setThreadPriority(mPriority);
           onLooperPrepared();
           Looper.loop();
           mTid = -1;
       }
      从源码可以看出,当run方法被执行后,会调用Looper.prepare()创建一个Looper对象和MessageQueue对象并绑定了在当前线程(异步线程);这样才可以Looper对象以参数的形式传给Handler对象,从而确保Handler的hanldMessage方法是在子线程(异步线程)中执行的;接下来会把创建的Looper对象赋值给HandlerThread的内部变量mLooper,并通过notifyAll方法唤醒等待线程,最后调用loop方法,中间有个onLooperPrepared方法,可以重写此方法,也就是说在loop开启循环之前,可以做一些其他的操作。有个疑问就是在loop开启循环之前,为什么要唤醒等待线程呢,接下来看看getLooper方法:
   

    /**
       * 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 .
         返回此线程关联的Looper对象
       */
      public Looper getLooper() {
         //如果线程没有开启,则返回null
           if (!isAlive()) {
              return null;
          }
     
          // If the thread has been   started, wait until the looper has been created.
           //如果线程被开启了,而且当前线程Looper为null时,此时会等待状态,直到mLooper被初始化并赋值后会被唤醒
           synchronized (this) {
              while (isAlive() &&   mLooper == null) {
                  try {
                      wait();
                  } catch   (InterruptedException e) {
                  }
              }
          }
          return mLooper;
      }
    当外部主线程调用getLooper方法,先会判断当前异步线程是否启动了,如果isAlive()为false   ,说明线程未开启,会返回null,如果线程启动了,则会进入同步代码块内并判断mLooper是否为null,也就是内部变量mLooper是否被赋值,为null表示未赋值尚未初始化,进入等待状态,直到mLooper被赋值后,notifyAll方法会唤醒所以的等待线程   ,最后返回Looper对象。   之所以有个等待唤醒机制,主要getLooper方法是在主线程调用的,而mLooper是在子线程初始化赋值的,也就是我们无法保证不同线程访问同一个对象   是否被创建了,也就是说在调用getLooper方法来获取Looper对象时,无法确保mLooper已经被创建了 ,,故引入等待唤醒机制来确保线程创建开启后   并且Looper对象 也被创建后才可以成功返回mLooper

    public boolean quit() {
        Looper looper =   getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
    &nbs   



本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

X
免费获取海同IT培训资料
验证码手机号,获得海同独家IT培训资料
获取验证码
提交

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    ICP许可  沪B2-20190160

站长统计