關於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
去不斷的處理訊息,啟動的程式碼在 ActivityThread
的 main
方法中程式碼如下:
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);
}
}
可以看到,當直接退出的時候,會把訊息佇列中所有的訊息都取消掉。如果是安全退出,會把延時的訊息取消掉,非延時的訊息會處理完。有點類似執行緒池ExecutorService
的 shutdown()
和 shutdownNow()
方法。
Looper 的 quitSafely 方法從 api level 18才可以使用
優點
HandlerThread
相比於Thread
一次建立執行緒,就可以不斷的處理訊息,減少了頻繁建立執行緒帶來的資源消耗。
使用場景
滿足以下兩個場景即可使用HandlerThread
- 需要子執行緒處理任務
- 要處理多個任務
使用
一個小demo
https://github.com/77Y/HandlerThread