HandlerThread相关问题总结

HandlerThread是什么

HandlerThread产生背景

开启Thread子线程进行耗时操作

多次创建和销毁线程是很耗系统资源的。

(为什么呢,因为java的线程是依托操作系统,线程的创建和销毁以及频繁切换都涉及到用户态和内核态的切换,以及线程上下文的保存和恢复,所以是比较耗资源的。)

HandlerThread 的特点

本质上就是封装了Handler的线程

  1. HandlerThread 本质是一个线程类,它继承自Thread
  2. HandlerThread 有自己的内部looper对象,可以进行loop循环
  3. 通过HandlerThread的looper对象传递给Handler对象,可以在handleMessage方法中执行异步任务
  4. 不会阻塞,减少了对性能的消耗,缺点是不能同时进行多任务的处理,需要等待进行,效率低。

这里的不会阻塞,指的是非UI线程,又想使用消息机制的那些操作。通过HandlerThread来执行是最合适的。

  1. 与线程池重并发不同,HandlerThread是一个串行队列,HandlerThread只有一个线程。

HandlerThread的用法

    1.创建HandlerThread
    HandlerThread handlerThread = new HandlerThread("handlerThread_name");

    //2.必须先开启线程
    handlerThread.start();

    /**
     * 3.设置callback
     * 该callback运行于子线程
     */
    class ChildCallback implements Handler.Callback {
        @Override
        public boolean handleMessage(Message msg) {
            //在子线程中进行相应的网络请求

            //通知主线程去更新UI
            mUIHandler.sendMessage(msg1);
            return false;
        }
    }

    //4.子线程Handler
    Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback());

HandlerThread源码分析

首先HandlerThread继承自Thread,说明它是一个线程,肯定需要实现run方法。
那它又号称内部集成了Handler,我们知道Handler的运行离不开Looper,
所以在run方法里面通过Looper.prepare()Looper.loop()开启一个Looper循环。

继承自Thread

public class HandlerThread extends Thread {
...
}

构造方法

    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.

run方法

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {//同步代码块,确保同一时刻只有一个线程可以访问mLooper
            mLooper = Looper.myLooper();
            notifyAll();//通知当前等待线程,主要是getLooper()方法里的wait方法
        }
        Process.setThreadPriority(mPriority);//设定线程优先级
        onLooperPrepared();//空方法,留个用户自己重写
        Looper.loop();//初始化数据接收,开启循环。
        mTid = -1;
    }

getLooper()方法

    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {//同步代码块,如果looper没有创建成功,就一直阻塞,直到looper创建完毕。
            while (isAlive() && mLooper == null) {
                try {
                    //这个是没有设置TimeOut的Object:wait方法,无限期等待,必须是其他线程调用notify或者notifyAll才能唤醒。
                    //当run方法的mLooper对象创建完毕时,就会调用notifyAll方法唤醒。
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

quit和quitSafely方法

    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;
    }

quitsafely比quit更安全,各自的实现原理如下。

    //Looper.java
    public void quit() {
        mQueue.quit(false);
    }
    public void quitSafely() {
        mQueue.quit(true);
    }

    //MessageQueue.java
    void quit(boolean safe) {
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
        }

        synchronized (this) {
            if (mQuitting) {
                return;
            }
            mQuitting = true;

            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }

            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
    }

    private void removeAllMessagesLocked() {
        Message p = mMessages;
        while (p != null) {
            Message n = p.next;
            p.recycleUnchecked();
            p = n;
        }
        mMessages = null;
    }

    private void removeAllFutureMessagesLocked() {
        final long now = SystemClock.uptimeMillis();
        Message p = mMessages;
        if (p != null) {
            if (p.when > now) {
                removeAllMessagesLocked();
            } else {
                Message n;
                for (;;) {
                    n = p.next;
                    if (n == null) {
                        return;
                    }
                    if (n.when > now) {
                        break;
                    }
                    p = n;
                }
                p.next = null;
                do {
                    p = n;
                    n = p.next;
                    p.recycleUnchecked();
                } while (n != null);
            }
        }
    }
posted @ 2022-07-07 19:16  cfdroid  阅读(65)  评论(0编辑  收藏  举报