在 Android 中咱們常常要處理一些耗時任務,爲了不界面卡頓,咱們一般使用線程來完成這些工做,可是線程多了會浪費資源,甚至形成 OOM,詳情可參考 Android 建立線程源碼與OOM分析,咱們很容易想到使用線程池來重複利用線程。bash
可是有時咱們的任務須要同時只能執行一個,舉個栗子ide
咱們要寫一個視頻播放器,若是在主線程中操做 MediaPlayer 會致使界面不流暢,這時就須要在後臺線程中處理,並且同時只能有一個線程操做 MediaPlayer,否則就可能出問題。oop
有人說,用 SingleThreadPool 不就行了,的確可使用單線程的線程池,可是其實咱們有更輕量的選擇,沒錯,使用 HandlerThread,今天咱們的主角就是它。ui
HandlerThread 的用法你們確定已經很熟悉了,本文也不是爲了介紹 HandlerThread 的使用方法。this
HandlerThread handlerThread = new HandlerThread("name");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
複製代碼
HandlerThread 繼承自 Thread,那麼它和咱們熟知的 Thread 有何不一樣呢?spa
咱們知道普通的 Thread 在 run 方法執行完就會進入終止狀態,而 HandlerThread 複寫了 start 方法,在 start 時建立了 Looper,並開啓了 loop 循環線程
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
複製代碼
所以 HandlerThread 不會自動終止,除非咱們手動調用 getLooper().quit()
跳出 loop 循環。code
前段時間項目中須要實現一個視頻播放器,對於 MediaPlayer 的操做經過 HandlerThread 完成,每次 new 一個播放器都會啓動一個 HandlerThread,而播放器銷燬時並無中止 HandlerThread。咱們 APP 中訪問量最大的商品詳情頁也使用了這個播放器,上線後發現APP的線程數量增長了不少,仔細一看,發現有不少名爲 VideoPlayer
的線程,恍然大悟。cdn
還好沒有引起嚴重的問題,不過線程數量過多也會形成 OOM,存在很大的風險,因此馬不停蹄發補丁修復問題。視頻
回想起來,原來本身一直都沒有注意到 HandlerThread 須要手動中止,爲了加深記憶,發文以記錄。
今天是七夕節,不知道你們是否是都在陪妹子對酒賞月,反正杭州的颱風還沒走,哈哈
遷移自個人簡書 2018.08.17