Android线程之HandlerThread

作者: smart_dev | 来源:发表于2017-05-24 16:55 被阅读219次

    概述

    HandlerThread是Thread的一个子类,是Android中提供的另一种线程形态。

    Handy class for starting a new thread that has a looper. The looper can then be
    used to create handler classes. Note that start() must still be called.
    这个是官方类的说明。说这个类是一个带有Looper的线程,这个looper用来创建handler使用的。切记要调用start()方法来启动。

    我擦,有线程、有looper这不正是我们当初声称在子线程中构建handler消息系统的所需要的吗?

    源码分析

    看一下这个线程核心run()方法源码:

    @Override
    public void run() {
        mTid = Process.myTid(); //获得线程的id
        Looper.prepare();
        synchronized (this) {  // 之所以用同步代码块,是处理getLooper() 的同步问题,保证looper的获得。
            mLooper = Looper.myLooper();
            notifyAll(); //获取完毕后,通知getLooper()
        }
        Process.setThreadPriority(mPriority); //设置线程的优先级
        onLooperPrepared(); 
        Looper.loop();
        mTid = -1;
    }
    
    • Looper.prepare()创建LooperMessageQueue
    • 然后调用Looper.loop()是这个消息系统循环起来
    • onLooperPrepared() 这个方法是空方法体,子类可以重写这个方法,做些线程循环前的操作

    再看一下getLooper()源码:

    public Looper getLooper() {
        if (!isAlive()) { 
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        //如果线程活着但mLooper却是空的,则进入等待,等待mLooper被创建完毕
        //这里的wait方法 与 run方法中的 notifyAll 实现了线程的同步
        synchronized (this) {  
            while (isAlive() && mLooper == null) { 
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }
    

    那很明显,这个HandlerThread的目的就是让我们创建一个Handler,然后所有的任务操作成功的转给了Handler来处理完成。
    但注意的是这个Handler的消息处理是运行在子线程中的。

    用法

    在主线程中创建handler,简单的模拟一下HandlerThread工作原理

     @Override
     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // 创建HandlerThread
        HandlerThread handlerThread = new HandlerThread("handlerThread");
        // 必须调用start()方法进而执行run方法体
        handlerThread.start();
        //获得这个线程的looper
        Looper looper = handlerThread.getLooper();
        //创建这个looper对应的Handler
        handler = new Handler(looper) {
            @Override
            public void handleMessage(Message msg) {
                Log.d("smart", "当前的线程:" + Thread.currentThread().getName());
                if (msg.what == 2) {
                    Log.d("smart", "handleMessage: 收到了延迟消息 2");
                }
            }
        };
        Message message = Message.obtain();
        message.what = 2;
        handler.sendMessage(message);
    }
    
    QQ截图20170519162157.png

    由于这个handler回调是运行在子线程中的,因此如果你想要更新UI可以借助主线程的默认的looper来实现,这个问题又愉快的转化到了子线程更新UI的问题。

    除此之外,HandlerThread还提供了方法来退出消息循环,停止任务的执行。

    • quit()
    • quitSafely()

    总结

    HandlerThread其本质就是一个线程,只不过这个线程加入了Handler消息异步处理的机制。
    那这与普通的创建线程的好处是什么呢?

    • HandlerThread自带Looper使他可以通过消息来多次重复使用当前线程,节省开支;
    • android系统提供的Handler类内部的Looper默认绑定的是UI线程的消息队列,对于非UI线程又想使用消息机制,于是HandlerThread就被登场了,它不会干扰或阻塞UI线程;
    • 在一个,线程有了消息队列的机制,那任务的控制顺序等都交给了优秀的Handler异步消息机制,有种托管的轻松。
    • Android中的IntentService中就使用了HanlderThread

    相关文章

      网友评论

        本文标题:Android线程之HandlerThread

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