美文网首页
HandlerThread使用&原理解析

HandlerThread使用&原理解析

作者: 北疆小兵 | 来源:发表于2019-10-22 15:51 被阅读0次

HanlderThread

定义

一个便利地启动带有Looper的「新线程」的类, 该Looper可以用来创建Handler类,使用HanderThread类必须调用start()方法

作用

1.在工作线程中执行耗时任务
2.异步通信、消息传递

优点

  1. 方便使用异步通信
  2. 不需要使用"任务线程(如继承Thread类)"+Handler类的复杂组合
  3. 当希望停止时可以执行.quit()或者quitSafely()来结束当前线程运行()

工作原理

HandlerThread本质上是一个线程类,他与普通Thread类型不同之处在于在它执行run方法时,其内部会持有Looper并调用Looper.loop开启循环读取MessageQueue中的消息, 创建Handler时绑定HandlerThread中的Looper对象,这样Hanler就和HandlerThrad中的Looper对象就关联起来了

使用步骤

1.创建HandlerThread实例
2.调用HandlerThread实例的start()方法启动线程
3.使用HandlerThread实例的Looper对象创建Handler
4.使用Handler发送消息

实例讲解

private Handler mHandler;
HandlerThread handlerThread = new HandlerThread("wrok_thread");
      handlerThread.start();
        mHandler = new Handler(handlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                MainLogUtil.d("handleMessage what = %s, threadName = %s", msg.what,Thread.currentThread().getName());
            }
        };

 private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(2000);
                    MainLogUtil.d("第 %s 个 任务 %s, threadName: %s", clickCount,i,Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            clickCount++;
        }
    };
    
    
输出如下:
    
    ![](media/15717279639790/15717291931427.jpg)


    
    

连续点击两次按钮执行任务,发现第2次点击的任务不是马上执行而是等待第1次任务执行完成再执行第2次任务

源码分析


public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;

    
    protected void onLooperPrepared() {
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
   public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

 
    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }

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

       public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}





可以看出HandlerThread的源码非常简单,跟普通Thread类最大的区别是在start方法中开启了Looper循环,Looper内部维护了一个消息队列,Looper会循环从消息队列中取出消息顺序执行,当我们使用Handler(绑定了HanlderThread类中的Looper对象)发送消息的时候,会发送到Looper的MessageQueue中, Looper对象的loop方法开启死循环从MessageQueue中取出Message对象,调用其Message.tartget.dispatch()方法,最后回调到Handler的handleMessage方法

总结

HandlerThrad可以替换Handler+Thread的复杂组合做耗时操作, 由于其绑定的Looper是循环从消息队列中按顺序取出Message执行,因此适合单线程操作,当然这也是其缺点,当某个任务执行耗时过长时,后面排队的任务必须等前面的任务执行完成之后才能执行。

相关文章

网友评论

      本文标题:HandlerThread使用&原理解析

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