Android系統中異步消息處理線程機制的理解

Android系統中異步消息處理線程機制的理解

 普通線程:對於一般的線程模型,執行完run()方法內的代碼後線程就結束了。
 異步線程:線程啓動後會進入一個無限的循環體之中,每次循環,從其內部的消息隊列中取出一個消息,並回調相應的消息處理函數,執行完一個消息後繼續循環。如果消息隊列爲空,線程會暫停,直到消息隊列中有新的消息。
 異步消息處理本質是仍然是一個線程,只不過這個線程的執行代碼邏輯被設置成了異步線程模型所需要的。
 異步線程的應用需求:
1)任務需要常駐。比如處理用戶交互,網絡請求處理等任務。
2)任務需要根據外部傳遞的消息做不同的操作。比如,根據不同消息,對不同任務的分發等
 
 Android系統中的實現機制:
 
  在android中實現異步線程主要涉及到如下幾個類:ThreadLocal,Looper,MessageQueue,Handler,Message。
 下面是網上的一張異步線程實現類的關係圖:

ThreadLocal

ThreadLocal並不是Android的sdk中的類,而是java.lang中的一個類,該類的作用是爲線程創建一個基於線程的變量存儲,稱之爲線程局部存儲

簡單的說,就是作用域在線程內,本線程內的該類的任何對象保持一致。

ThreadLocal可以使對象達到線程隔離的目的,它爲每一個線程維護自己的變量拷貝,通過其中的set方法將變量綁定到線程上。ThreadLocal提供了一種解決多線程同步的問題解決方案,通過爲每一份變量進行拷貝,這樣的話,每個線程操作的都是屬於自己的變量,而不是共同的一個變量,因此也就不需要同步鎖了。在Android的異步線程中,ThreadLocal綁定的這個線程變量就是Looper的一個對象。

Looper類

Looper只是產生一個消息循環框架,首先Looper創建了消息隊列(MessageQueue)並把它掛接在Linux的線程上下文中,進入到取消息,並分發消息的循環當中Looper 類用來爲一個線程跑一個消息循環。線程在默認情況下是沒有消息循環與之關聯的,Thread類在run()方法中的內容執行完之後就退出了,即線程做完自己的工作之後就結束了,沒有循環的概念。

在Looper類中有一個成員變量mQueue(MessageQueue類的實例),該變量用於保存Looper中MessageQueue。 Looper通過靜態方法Looper.prepare()方法來創建出一個MessageQueue對象。調用Looper類的 prepare() 方法可以爲當前線程創建一個消息循環,調用loop() 方法使之處理信息,直到循環結束。注意,Looper.prepare()方法在一個線程中只能執行一次。大多數和消息循環的交互是通過 Handler 類進行的。

 class LooperThread extends Thread {
      public Handler mHandler;
      public void run() {
          Looper.prepare();
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
          Looper.loop();
      }
  }

Handler類  

  

Handler類用來發送和處理消息(Message)以及和線程的消息隊列(MessageQueue)關聯的Runnable對象。Handler對象在同一個線程上下文中取得消息隊列,對消息隊列進行封裝操作,最主要的就是SendMessage和擔當起dispatchMessage這個實際工作。

外部系統需要向某個Android線程發送消息,必須通過屬於該AndroidThread的Handler這個對象每一個Handler對象都僅和一個線程及這個線程的消息隊列關聯。一個特定線程的所有Handler對象都會收到同樣的方法。(這是一個“一對多”的關係)。如下圖(圖片來自網絡)所示:


  當你創建一個新的Handler對象,它會和創建它的這個線程/線程的消息隊列綁定,從那個時刻開始,它將向這個消息隊列傳遞消息和runnable對象,並且當它們從隊列中出來時執行它們。

  Handler主要有兩種用途:

  1.合理調度安排消息和runnable對象,使它們在將來的某個點被執行。

  2.將一個動作入隊安排在非當前線程執行。

Handler屬於某個線程,取決Handlerd對象在哪個線程中建立Handler在構建時做了如下的默認動作:

  • 從線程上下文取得Looper
 
  • 通過Looper獲取到消息隊列並記錄在自己的成員mQueue變量中


Handler使用消息隊列進行對象封裝,提供如下的成員函數:

  • 通過  post(Runnable r)發送。Runnable是消息處理的回調函數,通過該消息的發送,引起Runable 的回調運行,post消息放置消息隊列的前面。Message.callback=Runable.
 
  • 通過 sendMessage發送。放置在所有的Post消息之後,sendMessage發送消息.

  • dispatchMessage分發消息。消息帶有回調函數,則執行消息回調函數,如何沒有則使用默認處理函數:handleMessage。而handleMessage往往被重載成某個繼承
     Handler對象的新的特定的handleMessage。幾乎所有的Message發送時,都指定了target。Message.target=(this).
Handler對象的post方法和sendMessage方法本質上都是發送消息的方法(post類方法實質上是調用了sendMessage方法)。所謂發送消息就是把消息放入消息隊列中的合適位置,並且把消息的target設置爲本Handler對象
所以當隊列中的消息處理的時候,也會找到當時送它來的Handler對象,調用其相應的dispatchMessage()方法,進而調用其中的handleMessage()方法或者mCallback成員的handleMessage()方法來進行處理。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章