Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Thread、Handler和HandlerThread關系詳解

Thread、Handler和HandlerThread關系詳解

編輯:關於Android編程

前言

前幾天看到一道面試題:Thread、Handler和HandlerThread有什麼區別?,這個題目有點意思,對於很多人來說,可能對Thread和Handler很熟悉,主要涉及到Android的消息機制(Handler、Message、Looper、MessageQueue),詳見《 從Handler.post(Runnable r)再一次梳理Android的消息機制(以及handler的內存洩露)》

但是這個HandlerThread是拿來做什麼的呢?它是Handler還是Thread?我們知道Handler是用來異步更新UI的,更詳細的說是用來做線程間的通信的,更新UI時是子線程與UI主線程之間的通信。那麼現在我們要是想子線程與子線程之間的通信要怎麼做呢?當然說到底也是用Handler+Thread來完成(不推薦,需要自己操作Looper),Google官方很貼心的幫我們封裝好了一個類,那就是剛才說到的:HandlerThread。(類似的封裝對於多線程的場景還有AsyncTask)

使用方法

還是先來看看HandlerThread的使用方法:
首先新建HandlerThread並且執行start()

private HandlerThread mHandlerThread;
......
mHandlerThread = new HandlerThread("HandlerThread");
handlerThread.start();

創建Handler,使用mHandlerThread.getLooper()生成Looper:

 final Handler handler = new Handler(mHandlerThread.getLooper()){
   @Override
   public void handleMessage(Message msg) {
    System.out.println("收到消息");
   }
  };

然後再新建一個子線程來發送消息:

 new Thread(new Runnable() {
   @Override
   public void run() {
    try {
     Thread.sleep(1000);//模擬耗時操作
     handler.sendEmptyMessage(0);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }).start();

最後一定不要忘了在onDestroy釋放,避免內存洩漏:

 @Override
 protected void onDestroy() {
  super.onDestroy();
  mHandlerThread.quit();
 }

執行結果很簡單,就是在控制台打印字符串:收到消息

原理

整個的使用過程我們根本不用去關心Handler相關的東西,只需要發送消息,處理消息,Looper相關的東西交給它自己去處理,還是來看看源碼它是怎麼實現的,先看構造方法:

public class HandlerThread extends Thread {}

HandlerThread其實還是一個線程,它跟普通線程有什麼不同?

public class HandlerThread extends Thread {
 int mPriority;
 int mTid = -1;
 Looper mLooper;

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

答案是多了一個Looper,這個是子線程獨有的Looper,用來做消息的取出和處理。繼續看看HandlerThread這個線程的run方法: 

 protected void onLooperPrepared() {
 }
 @Override
 public void run() {
  mTid = Process.myTid();
  Looper.prepare();
  synchronized (this) {
   mLooper = Looper.myLooper();//生成Looper
   notifyAll();
  }
  Process.setThreadPriority(mPriority);
  onLooperPrepared();//空方法,在Looper創建完成後調用,可以自己重寫邏輯
  Looper.loop();//死循環,不斷從MessageQueue中取出消息並且交給Handler處理
  mTid = -1;
 }

主要就是做了一些Looper的操作,如果我們自己使用Handler+Thread來實現的話也要進行這個操作,再來看看getLooper()方法:   

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

方法很簡單,就是加了個同步鎖,如果已經創建了(isAlive()返回true)但是mLooper為空的話就繼續等待,直到mLooper創建成功,最後看看quit方法,值得一提的是有兩個:

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

quitSafely是針對在消息隊列中還有消息或者是延遲發送的消息沒有處理的情況,調用這個方法後都會被停止掉。

總結

HandlerThread的使用方法還是比較簡單的,但是我們要明白一點的是:如果一個線程要處理消息,那麼它必須擁有自己的Looper,並不是Handler在哪裡創建,就可以在哪裡處理消息的。

如果不用HandlerThread的話,需要手動去調用Looper.prepare()和Looper.loop()這些方法。

以上就是對Thread、Handler和HandlerThread關系 的資料整理,後續繼續補充相關資料,謝謝大家對本站的支持!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved