HandlerThread 你真的用對了嗎?

前言

在 Android 中咱們常常要處理一些耗時任務,爲了不界面卡頓,咱們一般使用線程來完成這些工做,可是線程多了會浪費資源,甚至形成 OOM,詳情可參考 Android 建立線程源碼與OOM分析,咱們很容易想到使用線程池來重複利用線程。bash

可是有時咱們的任務須要同時只能執行一個,舉個栗子ide

咱們要寫一個視頻播放器,若是在主線程中操做 MediaPlayer 會致使界面不流暢,這時就須要在後臺線程中處理,並且同時只能有一個線程操做 MediaPlayer,否則就可能出問題。oop

有人說,用 SingleThreadPool 不就行了,的確可使用單線程的線程池,可是其實咱們有更輕量的選擇,沒錯,使用 HandlerThread,今天咱們的主角就是它。ui

HandlerThread 原理

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

HandlerThread 踩坑

前段時間項目中須要實現一個視頻播放器,對於 MediaPlayer 的操做經過 HandlerThread 完成,每次 new 一個播放器都會啓動一個 HandlerThread,而播放器銷燬時並無中止 HandlerThread。咱們 APP 中訪問量最大的商品詳情頁也使用了這個播放器,上線後發現APP的線程數量增長了不少,仔細一看,發現有不少名爲 VideoPlayer 的線程,恍然大悟。cdn

還好沒有引起嚴重的問題,不過線程數量過多也會形成 OOM,存在很大的風險,因此馬不停蹄發補丁修復問題。視頻

回想起來,原來本身一直都沒有注意到 HandlerThread 須要手動中止,爲了加深記憶,發文以記錄。

結語

今天是七夕節,不知道你們是否是都在陪妹子對酒賞月,反正杭州的颱風還沒走,哈哈

遷移自個人簡書 2018.08.17

相關文章
相關標籤/搜索