日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HandlerThread原理与应用

發布時間:2025/4/16 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HandlerThread原理与应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

HandlerThread


?在理解了Handler的原理之后,我們知道在一個子線程中創建一個Handler不能缺少了Looper.prepare()和Looper.loop()兩個方法,具體的原因這里不再贅述,不熟悉原理的可以先看下另一篇文章Handler的原理解析.
本篇文章主要是講解HandlerThread的使用的。
?首先HandlerThread是繼承于Thread類的,所以本質上HandlerThread就是一個線程,接下來就詳細的去看一看,這是怎樣的一個線程?
?首先,先看下它的構造函數:

public HandlerThread(String name) {super(name);mPriority = Process.THREAD_PRIORITY_DEFAULT;} public HandlerThread(String name, int priority) {super(name);mPriority = priority;} //很簡單,構造函數里只是設置了該Thread的名稱和優先級。

?既然是線程,那么最重要的當然是run方法來,看完了run方法,相信你也就明白HandlerThread的用途了!

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

?怎么樣,這是不是和我們之前在子線程中創建Handler一樣,首先是Looper.prepare(),接著是new Handler(), 最后是Looper.loop()。等等,這里并沒有創建Handler啊!別急,我們先一步一步地看看run方法再說為什么沒有創建Handler。

  • 首先呢是調用了Looper.prepaer(),該方法為我們的線程創建了一個唯一的Looper和MessageQueue對象,具體的創建過程看另一篇文章Handler的原理解析
  • 接下來有一個同步鎖的代碼塊,里面獲取到了創建好的Looper對象將其賦值給當前的mLooper,然后喚醒了鎖。注意這里有一個喚醒線程的操作,既然有喚醒鎖的操作,那么必定有有個地方使線程處于了阻塞的狀態,我們看下出現阻塞的地方。
  • 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;}

    ?通過查找發現到一個getLooper()的方法,該方法返回了當前線程的mLooper對象,還記得Looper是在哪里進行賦值的嗎?在線程的run方法里,所以當線程啟動之后才能創建Looper并賦值給mLooper,這里的阻塞就是為了等待Looper的創建成功。同時該方法是用Public修飾的,說明該方法是提供外部調用的,Looper創建成功提供給外部使用。

  • 接著我們回到run方法,Looper和MessageQueue已經創建成功了,接下來就是啟動Looper循環了(即Looper.loop()),別忘了只有Looper循環啟動后我們才能時刻觀察著MessageQueue,只要有Message了才能立馬將Message取出來進行分發處理。
  • 在Looper.loop()之前還調用了一個onLooperPrepared()方法,這個方法是干嘛的呢? 看代碼可知,只是一個空方法,在使用HandlerThread時重寫該方法,方便在Looper輪詢消息之前做一些初始化的操作。
  • /*** Call back method that can be explicitly overridden if needed to execute some* setup before Looper loops.*/protected void onLooperPrepared() {}

    ?最后在對象銷毀前,調用下面的方法退出Looper循環

    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;}

    ?quit方法實際是調用MessagQueue的removeAllMessagesLocked,移除所有延遲和非延遲的消息,
    ?quitSafely方法調用的是removeAllFutureMessagesLocked方法,該方法只清除延遲的消息,非延遲的消息
    還是會進行分發處理。


    ?HandlerThread分析完啦,是不是有點蒙,自始至終都沒有出現Handler,HandlerThread要怎么用呢?
    ?下面我們就通過一個Demo來說明下HandlerThread是怎么用的?

    private WorkHandler mHandler;private HandlerThread mHandlerThread;/*Handler存在一個構造函數,傳入一個Looper對象,Handler的handleMessage獲取的是Looper的MessageQueue中的Message因此,handleMessage的調用與Looper對象同屬于一個線程,這里我們在構造時傳入HandlerThread的Looper對象,handleMessage運行于HandlerThread線程(也就是一個子線程),所以Handler雖然是在住線程創建,但是它的handleMessage接收到消息是在HandlerThread線程,執行下代碼可以看到打印出如下log:D/HandlerThreadDemo: HandlerThread/Demo thread receiver the message from thread: mainlog也說明,message由主線程傳遞到了HandlerThread中。*/private class WorkHandler extends Handler {WorkHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);String str = (String) msg.obj;Log.d(TAG, Thread.currentThread().getName() + " thread receiver the message from thread: " + msg.obj);}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_handlerthread_demo);mHandlerThread = new HandlerThread("HandlerThread/Demo");mHandlerThread.start();mHandler = new WorkHandler(mHandlerThread.getLooper());Message msg = mHandler.obtainMessage();msg.obj = Thread.currentThread().getName();mHandler.sendMessage(msg);}

    總結:

  • HandlerThread繼承于Thread,本質上也是一個線程。
  • HandlerThread的run方法為本線程創建提供了Looper和MessageQueue對象,并開啟了Looper輪詢消息。
  • 通過在需要發送Message的線程中創建Handler,為Handler提供來自HandlerThread的Looper對象。Handler則能
    將消息發送到HandlerThread上去進行處理。
    注意:這里Handler不僅僅能在主線程創建,在子線程同樣能夠創建,只需要將對應的Looper提供給Handler即可,所以HandlerThread
    不僅適用于和主線程通信,同樣適用于和其他子線程通信。
  • 最后需要注意的是在我們不需要這個looper線程的時候需要手動停止掉,即調用quit()或者quitSafely()。
  • 最后補充一個在實際開發過程中使用到HandlerThread的場景:
    存在多個耗時的任務需要放到開啟子線程依次去處理(串行處理任務),首先,HandlerThread是一個子線程,
    適合處理耗時的任務,其次,Handler分發消息是通過MessageQueue頂部的Message不斷的通過Message的next依次取出
    Message,符合任務的按順序串行處理的要求,所以使用HandlerThread就能完美的解決此需求。
  • 總結

    以上是生活随笔為你收集整理的HandlerThread原理与应用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。