1. 程式人生 > >關於HandlerThread你應該知道的一切

關於HandlerThread你應該知道的一切

什麼是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
https://github.com/77Y/HandlerThread

關注微信公眾號,最新技術乾貨實時推送