关于HandlerThread你应该知道的一切

/ 移动技术 / 没有评论 / 223浏览

什么是HandlerThread

先来看看官方给的说明

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.

从它的名字 HandlerThread 说明它本质上还是一个Thread,只不过前面加了一个定语Handler。可以猜测这个Thread里包含了一个Handler,有Handler肯定还少不了Looper

在Android中,主线程会自动启动一个Looper去不断的处理消息,启动的代码在 ActivityThreadmain方法中代码如下:


public static void main(String[] args) {

	...
    Looper.prepareMainLooper();
	...
	
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    Looper.loop();
	...
}

这样系统处理一些消息就可以通过Handler发送消息到Looper的消息队列。如果我们也想有这样的一个消息处理系统怎么办呢,答案就是用HandlerThread

先来看一下HandlerThread的关键代码

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

可以看到首先调用了 Looper.prepare() ,然后调用了 Looper.loop() 和主线程启动类似。在Looper.loop()方法中执行了一个for循环,不断从消息队列(MessageQueue)中取出消息处理。

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

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

有两个quit方法,这两个quit方法有什么区别呢?直接看下代码(Looper.java)

public void quit() {
    mQueue.quit(false);
}

public void quitSafely() {
    mQueue.quit(true);
}

最终调用的都是mQueue.quit方法

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

可以看到,当直接退出的时候,会把消息队列中所有的消息都取消掉。如果是安全退出,会把延时的消息取消掉,非延时的消息会处理完。有点类似线程池ExecutorServiceshutdown()shutdownNow()方法。

Looper 的 quitSafely 方法从 api level 18才可以使用

优点

HandlerThread相比于Thread一次创建线程,就可以不断的处理消息,减少了频繁创建线程带来的资源消耗。

使用场景

满足以下两个场景即可使用HandlerThread

使用

一个小demo