Thread、Handler和HandlerThread關(guān)系詳解
前言
前幾天看到一道面試題:Thread、Handler和HandlerThread有什么區(qū)別?,這個(gè)題目有點(diǎn)意思,對于很多人來說,可能對Thread和Handler很熟悉,主要涉及到Android的消息機(jī)制(Handler、Message、Looper、MessageQueue),詳見《 從Handler.post(Runnable r)再一次梳理Android的消息機(jī)制(以及handler的內(nèi)存泄露)》
但是這個(gè)HandlerThread是拿來做什么的呢?它是Handler還是Thread?我們知道Handler是用來異步更新UI的,更詳細(xì)的說是用來做線程間的通信的,更新UI時(shí)是子線程與UI主線程之間的通信。那么現(xiàn)在我們要是想子線程與子線程之間的通信要怎么做呢?當(dāng)然說到底也是用Handler+Thread來完成(不推薦,需要自己操作Looper),Google官方很貼心的幫我們封裝好了一個(gè)類,那就是剛才說到的:HandlerThread。(類似的封裝對于多線程的場景還有AsyncTask)
使用方法
還是先來看看HandlerThread的使用方法:
首先新建HandlerThread并且執(zhí)行start()
private HandlerThread mHandlerThread;
......
mHandlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
創(chuàng)建Handler,使用mHandlerThread.getLooper()生成Looper:
final Handler handler = new Handler(mHandlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
System.out.println("收到消息");
}
};
然后再新建一個(gè)子線程來發(fā)送消息:
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);//模擬耗時(shí)操作
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
最后一定不要忘了在onDestroy釋放,避免內(nèi)存泄漏:
@Override
protected void onDestroy() {
super.onDestroy();
mHandlerThread.quit();
}
執(zhí)行結(jié)果很簡單,就是在控制臺打印字符串:收到消息
原理
整個(gè)的使用過程我們根本不用去關(guān)心Handler相關(guān)的東西,只需要發(fā)送消息,處理消息,Looper相關(guān)的東西交給它自己去處理,還是來看看源碼它是怎么實(shí)現(xiàn)的,先看構(gòu)造方法:
public class HandlerThread extends Thread {}
HandlerThread其實(shí)還是一個(gè)線程,它跟普通線程有什么不同?
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
......
}
答案是多了一個(gè)Looper,這個(gè)是子線程獨(dú)有的Looper,用來做消息的取出和處理。繼續(xù)看看HandlerThread這個(gè)線程的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創(chuàng)建完成后調(diào)用,可以自己重寫邏輯
Looper.loop();//死循環(huán),不斷從MessageQueue中取出消息并且交給Handler處理
mTid = -1;
}
主要就是做了一些Looper的操作,如果我們自己使用Handler+Thread來實(shí)現(xiàn)的話也要進(jìn)行這個(gè)操作,再來看看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;
}
方法很簡單,就是加了個(gè)同步鎖,如果已經(jīng)創(chuàng)建了(isAlive()返回true)但是mLooper為空的話就繼續(xù)等待,直到mLooper創(chuàng)建成功,最后看看quit方法,值得一提的是有兩個(gè):
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是針對在消息隊(duì)列中還有消息或者是延遲發(fā)送的消息沒有處理的情況,調(diào)用這個(gè)方法后都會被停止掉。
總結(jié)
HandlerThread的使用方法還是比較簡單的,但是我們要明白一點(diǎn)的是:如果一個(gè)線程要處理消息,那么它必須擁有自己的Looper,并不是Handler在哪里創(chuàng)建,就可以在哪里處理消息的。
如果不用HandlerThread的話,需要手動去調(diào)用Looper.prepare()和Looper.loop()這些方法。
以上就是對Thread、Handler和HandlerThread關(guān)系 的資料整理,后續(xù)繼續(xù)補(bǔ)充相關(guān)資料,謝謝大家對本站的支持!
相關(guān)文章
Android 中RecyclerView多種item布局的寫法(頭布局+腳布局)
這篇文章主要介紹了Android 中RecyclerView多種item布局的寫法(頭布局+腳布局)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01
Android開發(fā)之Notification通知用法詳解
這篇文章主要介紹了Android開發(fā)之Notification通知用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Notification通知的功能、參數(shù)、定義及使用方法,需要的朋友可以參考下2016-11-11
21天學(xué)習(xí)android開發(fā)教程之SQLite分頁讀取
21天學(xué)習(xí)android開發(fā)教程之SQLite分頁讀取,Android包含了常用于嵌入式系統(tǒng)的SQLite,免去了開發(fā)者自己移植安裝的功夫,感興趣的朋友可以參考一下2016-02-02
android studio 安裝完成ButterKnife插件卻無法使用(解決方案)
這篇文章主要介紹了android studio 安裝完成ButterKnife插件卻無法使用問題,本文通過圖文并茂的形式給大家分享解決方法,對大家有非常好的幫助,需要的朋友可以參考下2020-03-03
Android無需讀寫權(quán)限通過臨時(shí)授權(quán)讀寫用戶文件詳解
這篇文章主要為大家介紹了Android無需讀寫權(quán)限通過臨時(shí)授權(quán)讀寫用戶文件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
GuideView的封裝實(shí)現(xiàn)app功能引導(dǎo)頁
這篇文章主要為大家詳細(xì)介紹了GuideView的封裝實(shí)現(xiàn)app功能引導(dǎo)頁,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03
Android ViewPager自定義輪播圖并解決播放沖突
這篇文章主要為大家詳細(xì)介紹了Android ViewPager自定義輪播圖并解決播放沖突,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Android?性能優(yōu)化實(shí)現(xiàn)全量編譯提速的黑科技
這篇文章主要為大家介紹了Android?性能優(yōu)化實(shí)現(xiàn)全量編譯提速的黑科技,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
簡單實(shí)現(xiàn)安卓里百度地圖持續(xù)定位
本文主要介紹了在安卓的百度地圖開發(fā)里面簡單實(shí)現(xiàn)持續(xù)定位的方法,具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01

