HandlerThread源碼分析

HandlerThread作為子線程管理常用類(lèi),他自帶封裝的Looper處理Message,可以說(shuō)是十分實(shí)用。子線程調(diào)度任務(wù),方便我們?cè)谧泳€程中做更多的花樣。

介紹:

HandlerThread內(nèi)部實(shí)現(xiàn)很簡(jiǎn)單,主要用在需要進(jìn)行子線程調(diào)度任務(wù)的時(shí)候創(chuàng)建,但是想要完善熟悉原理,你必須熟悉Handler的內(nèi)部原理實(shí)現(xiàn)。請(qǐng)看我的文章:【Android源碼篇】 最詳細(xì)的AsyncTask源碼剖析

看完本文你會(huì)知道:

  1. HandlerThread的用法

  2. HandlerThread內(nèi)部原理

HandlerThread用法

1.創(chuàng)建使用

  • 創(chuàng)建HandlerThread,HandlerThread其實(shí)就是繼承的Thread類(lèi)

  • 將HandlerThread的looper綁定到Handler

      //創(chuàng)建HandlerThread
      mHandlerThread = new HandlerThread("handlerThread-test");
      mHandlerThread.start();
      //將HandlerThread的looper綁定到Handler
      mHandler = new Handler(mHandlerThread.getLooper(), new Handler.Callback() {
             @Override
             public boolean handleMessage(Message msg) {
                      switch (msg.what) {
                               case DELAY_1000:
                                        String str = (String) msg.obj;
                                        Log.d("handlerThread-test", "looper : DELAY_1000 " + str + "   處理線程:" + Thread.currentThread().getName());
                                        break;
                               case DELAY_2000:
                                        String str1 = (String) msg.obj;
                                        Log.d("handlerThread-test", "looper : DELAY_2000 " + str1 + "   處理線程:" + Thread.currentThread().getName());
                                        break;
                               case DELAY_3000:
                                        String str2 = (String) msg.obj;
                                        Log.d("handlerThread-test", "looper : DELAY_3000 " + str2 + "   處理線程:" + Thread.currentThread().getName());
                                        break;
                               case DELAY_4000:
                                        String str3 = (String) msg.obj;
                                        Log.d("handlerThread-test", "looper : DELAY_4000 " + str3 + "   處理線程:" + Thread.currentThread().getName());
                                        break;
                      }
                      return false;
             }
      });
    

2.測(cè)試

  • 在不同線程調(diào)度使用

      //測(cè)試
      new Thread(new Runnable() {
             @Override
             public void run() {
                      try {
                               Thread.sleep(1000);
                      } catch (InterruptedException e) {
                               e.printStackTrace();
                      }
                      asyncMessage(DELAY_1000, 0, "在子線程延時(shí)1s發(fā)送  調(diào)用線程:" + Thread.currentThread().getName());
             }
      }).start();
      asyncMessage(DELAY_2000, 2000, "在主線程延時(shí)2s發(fā)送  調(diào)用線程:" + Thread.currentThread().getName());
      mHandler.post(new Runnable() {
             @Override
             public void run() {
                      try {
                               Thread.sleep(3000);
                      } catch (InterruptedException e) {
                               e.printStackTrace();
                      }
                      asyncMessage(DELAY_3000, 0, "在post Runnable中sleep 3s  調(diào)用線程:" + Thread.currentThread().getName());
                      asyncMessage(DELAY_4000, 1000, "在DELAY_3000后延時(shí)1s發(fā)送  調(diào)用線程:" + Thread.currentThread().getName());
             }
      });
    
       private void asyncMessage(int what, int delay, String s) {
                Message message = mHandler.obtainMessage();
                message.what = what;
                message.obj = s;
                mHandler.sendMessageDelayed(message, delay);
       }
    
  • 結(jié)果:結(jié)果可以看出通過(guò)Handler對(duì)消息調(diào)度的處理,我們能在不同線程間進(jìn)行通訊,并最終在HandlerThread異步處理

      handlerThread-test: looper : DELAY_1000 在子線程延時(shí)1s發(fā)送  調(diào)用線程:Thread-5   處理線程:handlerThread-test
      handlerThread-test: looper : DELAY_2000 在主線程延時(shí)2s發(fā)送  調(diào)用線程:main   處理線程:handlerThread-test
      handlerThread-test: looper : DELAY_3000 在post Runnable中sleep 3s  調(diào)用線程:handlerThread-test   處理線程:handlerThread-test
      handlerThread-test: looper : DELAY_4000 在DELAY_3000后延時(shí)1s發(fā)送  調(diào)用線程:handlerThread-test   處理線程:handlerThread-test
    

3.退出

private void threadDestory() {     
      if (mHandlerThread != null) {
               mHandlerThread.quitSafely();
               mHandlerThread = null;
      }
}

HandlerThread源碼分析

查看HandlerThread內(nèi)部源碼,會(huì)發(fā)現(xiàn),其實(shí)就只有一點(diǎn)代碼,接下來(lái)一起分析吧

1. 構(gòu)造函數(shù)中指定線程等級(jí)

     /**
     * Standard priority of application threads.
     * Use with {@link #setThreadPriority(int)} and
     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
     * {@link java.lang.Thread} class.
     */
    public static final int THREAD_PRIORITY_DEFAULT = 0;
    
    ...

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

2. Run方法中初始化looper

    * 并調(diào)用   onLooperPrepared(looper執(zhí)行前執(zhí)行,用于處理一些準(zhǔn)備工作)
    *  Looper.myLooper();綁定當(dāng)前線程Looper輪詢(xún)器
    *  Looper.loop(); 開(kāi)始輪詢(xún)消息

     protected void onLooperPrepared() {
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

3. getLooper獲取當(dāng)前線程的輪詢(xún)器

    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

4. 退出輪詢(xún),還記得Handler源碼剖析里說(shuō)的,Looper quit時(shí)會(huì)清理MessageQueue里面所有的消息

    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
        looper.quitSafely();
        return true;
        }
        return false;
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容