HanlderThread
定义
一个便利地启动带有Looper的「新线程」的类, 该Looper可以用来创建Handler类,使用HanderThread类必须调用start()方法
作用
1.在工作线程中执行耗时任务
2.异步通信、消息传递
优点
- 方便使用异步通信
- 不需要使用"任务线程(如继承Thread类)"+Handler类的复杂组合
- 当希望停止时可以执行.quit()或者quitSafely()来结束当前线程运行()
工作原理
HandlerThread本质上是一个线程类,他与普通Thread类型不同之处在于在它执行run方法时,其内部会持有Looper并调用Looper.loop开启循环读取MessageQueue中的消息, 创建Handler时绑定HandlerThread中的Looper对象,这样Hanler就和HandlerThrad中的Looper对象就关联起来了
使用步骤
1.创建HandlerThread实例
2.调用HandlerThread实例的start()方法启动线程
3.使用HandlerThread实例的Looper对象创建Handler
4.使用Handler发送消息
实例讲解
private Handler mHandler;
HandlerThread handlerThread = new HandlerThread("wrok_thread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainLogUtil.d("handleMessage what = %s, threadName = %s", msg.what,Thread.currentThread().getName());
}
};
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(2000);
MainLogUtil.d("第 %s 个 任务 %s, threadName: %s", clickCount,i,Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
clickCount++;
}
};
输出如下:

连续点击两次按钮执行任务,发现第2次点击的任务不是马上执行而是等待第1次任务执行完成再执行第2次任务
源码分析
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
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;
}
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;
}
@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;
}
/**
* Returns the identifier of this thread. See Process.myTid().
*/
public int getThreadId() {
return mTid;
}
}
可以看出HandlerThread的源码非常简单,跟普通Thread类最大的区别是在start方法中开启了Looper循环,Looper内部维护了一个消息队列,Looper会循环从消息队列中取出消息顺序执行,当我们使用Handler(绑定了HanlderThread类中的Looper对象)发送消息的时候,会发送到Looper的MessageQueue中, Looper对象的loop方法开启死循环从MessageQueue中取出Message对象,调用其Message.tartget.dispatch()方法,最后回调到Handler的handleMessage方法
总结
HandlerThrad可以替换Handler+Thread的复杂组合做耗时操作, 由于其绑定的Looper是循环从消息队列中按顺序取出Message执行,因此适合单线程操作,当然这也是其缺点,当某个任务执行耗时过长时,后面排队的任务必须等前面的任务执行完成之后才能执行。
网友评论