android 多线程 — HandlerThread

2018-06-04  本文已影响56人  前行的乌龟

今天我们来看一个简单的 HandlerThread,前面我们学习过了 handle ,现在再来看 HandlerThread 会发现真是简单的不得了

HandlerThread 简单的说就是 在一个 Thread 里面封装了一个 looper ,然后启动该 looper ,外接和这个 HandlerThread 的交互都是通过 handle 发送消息,因为 HandlerThread 可以返回其虐不的 looper 对象,然后我们用这个 looper 对象创建 handle 对象发送消息

HandlerThread 的用法


        // 创建 HandlerThread 对象并启动 HandlerThread 所属线程,构造方法需要传线程的名字进去
        HandlerThread handlerThread = new HandlerThread("AAAAAAAA");
        handlerThread.start();

        // 通过 HandlerThread 对象内部的 looper 构建用于通讯的 handle
        Handler otherHandle = new Handler(handlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == 1) {
                    Log.d("AAA", Thread.currentThread().getName() + "接受消息" + System.currentTimeMillis());
                }
            }
        };

        // 执行线程间通讯任务
        otherHandle.sendMessage(Message.obtain());

        // 不需要了就关闭线程
        handlerThread.quit();

大家要是吧前面我说 handle 的那篇搞明白,这 HandlerThread 的使用实在不是要太简单了

看看源码吧


其实猜都能猜到的,这是 HandlerThread 声明的成员变量

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

这是核心 run 方法

    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

在线程启动时把 looper 消息队列跑起来

有意思的地方来了

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

大家注意 getLooper() 方法是给别的线程调用的,因为 handle 的构造方法不能接受 null 的 looper 对象,要不会抛异常,所以这里在其他线程获取 HandlerThread 的 looper 对象时,若是发现此时 looper 对象是 null 的,那么就会阻塞调用 getLooper() 方法的外部线程。

直到 run 的初始化同步代码段跑完,此时 looper 初始化完成,会主动唤醒所有阻碍在 looper 对象身上的 线程,我们再来看看 HandlerThread 的run 方法

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            // 主动唤醒所有阻碍在 looper 对象身上的 线程
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

好了,HandlerThread 很简单的,这里就基本完事了。我们看 HandlerThread 源码一定要理解 HandlerThread 为啥要 wait,什么时候 notifyAll 。这个是 HandlerThread 里面最值得学习的点,学会了很有用的。

参考资料


上一篇下一篇

猜你喜欢

热点阅读