Handler(八)--HandlerThread

系列目錄: Handler機(jī)制原理

1. HandlerThread介紹

當(dāng)系統(tǒng)有多個(gè)耗時(shí)任務(wù)需要執(zhí)行時(shí)舰罚,每個(gè)任務(wù)都會開啟一個(gè)新線程去執(zhí)行耗時(shí)任務(wù)逮栅,這樣會導(dǎo)致系統(tǒng)多次創(chuàng)建和銷毀線程挺身,從而影響性能挨下。為了解決這一問題蒿囤,Google提供了HandlerThread从隆,HandlerThread是在線程中創(chuàng)建一個(gè)Looper循環(huán)器,讓Looper輪詢消息隊(duì)列果复,當(dāng)有耗時(shí)任務(wù)進(jìn)入隊(duì)列時(shí)陈莽,則不需要開啟新線程,在原有的線程中執(zhí)行耗時(shí)任務(wù)即可据悔,否則線程阻塞传透。

2. 工作原理

  1. HandlerThread繼承Thread,在Thread開始執(zhí)行時(shí)跟主線程在ActivityThread.main()方法內(nèi)執(zhí)行代碼邏輯類似耘沼,初始化Looper--Looper.prepare(),輪詢消息--Looper.loop();
  2. 初始化Handler時(shí)极颓,使用HandlerThread線程的Looper對象初始化---- new Handler(Looper)構(gòu)造方法。
  3. 至于為什么是在子線程內(nèi)執(zhí)行是因?yàn)榇薍andler使用的Looper是子線程創(chuàng)建的群嗤,執(zhí)行message.target.dispatchMessage()也在子線程內(nèi)菠隆,所以最終執(zhí)行的Runnable或者h(yuǎn)andleMessage()也會在子線程內(nèi)。Handler為什么內(nèi)回主線程執(zhí)行也是如此。

3. 使用實(shí)例代碼

  // 步驟1:創(chuàng)建HandlerThread實(shí)例對象
  // 傳入?yún)?shù) = 線程名字骇径,作用 = 標(biāo)記該線程
  HandlerThread mHandlerThread = new HandlerThread("handlerThread");
  // 步驟2:啟動線程
  mHandlerThread.start();
  // 步驟3:創(chuàng)建工作線程Handler & 復(fù)寫handleMessage()
  // 作用:關(guān)聯(lián)HandlerThread的Looper對象躯肌、實(shí)現(xiàn)消息處理操作 & 與 其他線程進(jìn)行通信
  // 注:消息處理操作(HandlerMessage())的執(zhí)行線程 = mHandlerThread所創(chuàng)建的工作線程中執(zhí)行
  Handler workHandler = new Handler( handlerThread.getLooper() ) {
            @Override
            public boolean handleMessage(Message msg) {
                ...//消息處理
                return true;
            }
        });

  // 步驟4:使用工作線程Handler向工作線程的消息隊(duì)列發(fā)送消息
  // 在工作線程中,當(dāng)消息循環(huán)時(shí)取出對應(yīng)消息 & 在工作線程執(zhí)行相關(guān)操作
  // a. 定義要發(fā)送的消息
  Message msg = Message.obtain();
  //消息的標(biāo)識
  msg.what = 1;
  // b. 通過Handler發(fā)送消息到其綁定的消息隊(duì)列
  workHandler.sendMessage(msg);

// 步驟5:結(jié)束線程破衔,即停止線程的消息循環(huán)
  mHandlerThread.quit();

4. 源碼分析

4.1 實(shí)例化HandlerThread
public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    //當(dāng)前線程持有的Looper對象
    Looper mLooper;
    private @Nullable Handler mHandler;
    // 方式1. 默認(rèn)優(yōu)先級
    public HandlerThread(String name) {
        // 通過調(diào)用父類默認(rèn)的方法創(chuàng)建線程
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    // 方法2. 自定義設(shè)置優(yōu)先級
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    ...
}

HandlerThread類繼承自Thread類

4.2 啟動HandlerThread
    @Override
    public void run() {
        // 1. 獲得當(dāng)前線程的id
        mTid = Process.myTid();
        // 2. 創(chuàng)建1個(gè)Looper對象 & MessageQueue對象
        Looper.prepare();
        // 3. 通過持有鎖機(jī)制來獲得當(dāng)前線程的Looper對象
        synchronized (this) {
            mLooper = Looper.myLooper();
            // 發(fā)出通知:當(dāng)前線程已經(jīng)創(chuàng)建mLooper對象成功
            // 此處主要是通知getLooper()中的wait()
            notifyAll();
        }
        // 4. 設(shè)置當(dāng)前線程的優(yōu)先級
        Process.setThreadPriority(mPriority);
        // 5. 在線程循環(huán)前做一些準(zhǔn)備工作
        // 該方法實(shí)現(xiàn)體是空的清女,由子類決定是否實(shí)現(xiàn)
        onLooperPrepared();
        // 6. 進(jìn)行消息循環(huán),即不斷從MessageQueue中取消息 & 派發(fā)消息
        Looper.loop();
        mTid = -1;
    }

run()內(nèi)所做操作和ActivityThread.main()方法內(nèi)所操作的東西大體相類似晰筛。不同的是嫡丙,利用了鎖機(jī)制來保證getLooper()獲取looper正確。

4.3 獲取實(shí)例化Handler要用到的Looper
    public Looper getLooper() {
        // 若線程不是存活的读第,則直接返回null
        if (!isAlive()) {
            return null;
        } 
        // 若當(dāng)前線程存活曙博,再判斷線程的成員變量mLooper是否為null
        // 直到線程創(chuàng)建完Looper對象后才能獲得Looper對象,若Looper對象未創(chuàng)建成功怜瞒,則阻塞
        synchronized (this) {
  
      
            while (isAlive() && mLooper == null) {
                try {
                    // 此處會調(diào)用wait方法去等待
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        // 上述步驟run()使用 持有鎖機(jī)制 + notifyAll()  獲得Looper對象后
        // 則通知當(dāng)前線程的wait()結(jié)束等待 & 跳出循環(huán)
        // 最終getLooper()返回的是在run()中創(chuàng)建的mLooper對象
        return mLooper;
    }
  1. 在獲得HandlerThread工作線程的Looper對象時(shí)存在一個(gè)同步的問題:只有當(dāng)線程創(chuàng)建成功 & 其對應(yīng)的Looper對象也創(chuàng)建成功后才能獲得Looper的值父泳,才能將創(chuàng)建的Handler 與 工作線程的Looper對象綁定,從而將Handler綁定工作線程
  2. 解決方案:即保證同步的解決方案 = 同步鎖吴汪、wait() 和 notifyAll()惠窄,即 在run()中成功創(chuàng)建Looper對象后,立即調(diào)用notifyAll()通知 getLooper()中的wait()結(jié)束等待 & 返回run()中成功創(chuàng)建的Looper對象浇坐,使得Handler與該Looper對象綁定泼掠。

主要功能代碼既是如此,HandlerThread內(nèi)的其他源碼不再做額外分析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鱼填,一起剝皮案震驚了整個(gè)濱河市橘沥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌觉渴,老刑警劉巖介劫,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異案淋,居然都是意外死亡座韵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門踢京,熙熙樓的掌柜王于貴愁眉苦臉地迎上來誉碴,“玉大人,你說我怎么就攤上這事瓣距∏粒” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵蹈丸,是天一觀的道長成黄。 經(jīng)常有香客問我呐芥,道長,這世上最難降的妖魔是什么奋岁? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任思瘟,我火速辦了婚禮,結(jié)果婚禮上闻伶,老公的妹妹穿的比我還像新娘滨攻。我一直安慰自己,他們只是感情好蓝翰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布铡买。 她就那樣靜靜地躺著,像睡著了一般霎箍。 火紅的嫁衣襯著肌膚如雪奇钞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天漂坏,我揣著相機(jī)與錄音景埃,去河邊找鬼。 笑死顶别,一個(gè)胖子當(dāng)著我的面吹牛谷徙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播驯绎,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼完慧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了剩失?” 一聲冷哼從身側(cè)響起屈尼,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拴孤,沒想到半個(gè)月后脾歧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡演熟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年鞭执,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芒粹。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兄纺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出化漆,到底是詐尸還是另有隱情估脆,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布获三,位于F島的核電站旁蔼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疙教。R本人自食惡果不足惜棺聊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贞谓。 院中可真熱鬧限佩,春花似錦、人聲如沸裸弦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽理疙。三九已至晕城,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窖贤,已是汗流浹背砖顷。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赃梧,地道東北人滤蝠。 一個(gè)月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像授嘀,于是被迫代替她去往敵國和親物咳。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容