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ì)知道:
HandlerThread的用法
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;
}