Android系統(tǒng)中,執(zhí)行耗時(shí)操作都需要另外開(kāi)啟子線程來(lái)執(zhí)行,執(zhí)行完線程以后自動(dòng)銷(xiāo)毀。為了避免重復(fù)的創(chuàng)建和銷(xiāo)毀線程,避免過(guò)多的消耗性能,可以采用:
- 1.使用線程池
- 2.使用
HandlerThread
1.HandleThread 使用場(chǎng)景,以及如何使用
使用場(chǎng)景
HandlerThread是Google幫我們封裝好的,可以用來(lái)執(zhí)行多個(gè)耗時(shí)操作,而不需要多次創(chuàng)建銷(xiāo)毀線程,里面是采用Handler和Looper實(shí)現(xiàn)的。
使用方式
- 創(chuàng)建HandlerThread的實(shí)例對(duì)象
//構(gòu)造方法的參數(shù)表示的是線程的名稱(chēng)
HandlerThread mHandlerThread = new HandlerThread("wyw");
- 啟動(dòng)創(chuàng)建的實(shí)例對(duì)象
mHandlerThread.start()
- 將實(shí)例對(duì)象和handler綁定在一起。(必須按照這三步進(jìn)行)
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
checkForUpdate();
if (isUpdate) {
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
}
};
完整使用實(shí)例代碼:
public class MyActivity extends AppCompatActivity {
private static final int MSG_UPDATE_INFO = 0x100;
private HandlerThread mHandlerThread;
private Handler mThreadHandler;
Handler mMainHandler = new Handler();
private TextView tv;
private boolean isUpdate = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//創(chuàng)建handlerThread實(shí)例
mHandlerThread = new HandlerThread("wyw");
//啟動(dòng)handlerThread實(shí)例
mHandlerThread.start();
//handlerThread 綁定handler
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
checkForUpdate();
if (isUpdate) {
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
}
};
}
private void checkForUpdate() {
try {
//模擬耗時(shí)
Thread.sleep(1200);
mMainHandler.post(new Runnable() {
@Override
public void run() {
String result = "實(shí)時(shí)更新中, 當(dāng)前股票行情: <fontcolor='red'>%d</font>";
result = String.format(result, (int) Math.random() * 5000 + 1000);
tv.setText(result);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onResume() {
super.onResume();
isUpdate = true;
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
@Override
protected void onPause() {
super.onPause();
isUpdate = false;
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandlerThread.quit();
mMainHandler.removeCallbacksAndMessages(null);
}
}
2.HandlerThread源碼解析
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
//持有鎖機(jī)制來(lái)獲得當(dāng)前線程的Looper對(duì)象
synchronized (this) {
mLooper = Looper.myLooper();
//發(fā)出通知,當(dāng)前線程已經(jīng)創(chuàng)建mLooper對(duì)象成功,這里主要是通知getLooper方法中的waiter
notifyAll();
}
//線程的優(yōu)先級(jí)設(shè)置
Process.setThreadPriority(mPriority);
//方法空實(shí)現(xiàn),可以重寫(xiě)這個(gè)方法,處理線程開(kāi)啟之前的準(zhǔn)備工作
onLooperPrepared();
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
//直到線程創(chuàng)建完Looper之后才能獲取Looper對(duì)象,Looper未創(chuàng)建成功阻塞
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
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;
}
public int getThreadId() {
return mTid;
}
}
-
HandlerThread構(gòu)造方法,一個(gè)參數(shù)和兩個(gè)參數(shù)的,name代表當(dāng)前線程的名稱(chēng),priority代表線程的優(yōu)先級(jí)。 - 前面強(qiáng)調(diào)在使用
HandlerThread的時(shí)候必須先調(diào)用start(),接著才可以將HandlerThread和Handler綁定在一起。因?yàn)樵趓un()方法中,我們才初始化looper,而我們調(diào)用HandlerThread的start()方法的時(shí)候,線程會(huì)交給虛擬機(jī)調(diào)度,由虛擬機(jī)自動(dòng)調(diào)用run()方法。 - run()方法中使用鎖機(jī)制和notifyAll()的原因,可以在getLooper()方法中找到。
在獲取mLooper對(duì)象的時(shí)候存在一個(gè)同步的問(wèn)題,只有當(dāng)當(dāng)線程成功創(chuàng)建并且Looper對(duì)象也創(chuàng)建成功之后才能獲取mLooper的值。這里等待waite()和run()中的notifAll()共同實(shí)現(xiàn)同步。 -
quit()和quitSafe()的區(qū)別:
通過(guò)源碼追蹤,可以發(fā)現(xiàn),實(shí)際這個(gè)兩個(gè)方法最終調(diào)用的是MessageQueue.quit(boolean safe)。MessageQueue.quit方法源碼:
可以看出,這個(gè)方法根據(jù)傳入的參數(shù)safe來(lái)判斷執(zhí)行removeAllFutureMessagesLocked()或removeAllMessagesLocked()。void quit(boolean safe) { if (!mQuitAllowed) { throw new IllegalStateException("Main thread not allowed to quit."); } synchronized (this) { if (mQuitting) { return; } mQuitting = true; if (safe) { removeAllFutureMessagesLocked(); } else { removeAllMessagesLocked(); } // We can assume mPtr != 0 because mQuitting was previously false. nativeWake(mPtr); } }
如果不是安全退出,執(zhí)行removeAllMessagesLocked(),該方法就是遍歷Message鏈表,移除所有信息的回調(diào),并重置為null。private void removeAllMessagesLocked() { Message p = mMessages; while (p != null) { Message n = p.next; p.recycleUnchecked(); p = n; } mMessages = null; }
如果是安全的退出,執(zhí)行removeAllFutureMessagesLocked(),該方法,根據(jù)private void removeAllFutureMessagesLocked() { final long now = SystemClock.uptimeMillis(); Message p = mMessages; if (p != null) { if (p.when > now) { removeAllMessagesLocked(); } else { Message n; for (;;) { n = p.next; if (n == null) { return; } if (n.when > now) { break; } p = n; } p.next = null; do { p = n; n = p.next; p.recycleUnchecked(); } while (n != null); } } }Message.when這個(gè)屬性,判斷我們當(dāng)前消息隊(duì)列是否正在處理消息,沒(méi)有處理消息的話,直接移除所有的回調(diào),正在處理的話,等待該消息處理完畢再退出該循環(huán)。因此說(shuō)quiteSafe()是安全的,而quit()是不安全的,因?yàn)閝uit()不管是否正在處理,直接移除所有的回調(diào)。