日常开发我们做耗时任务时都是直接创建一个线程去执行,执行完毕后又销毁。当然这样做并没什么毛病,但是如果执行的耗时任务很多,每个任务我们都要创建线程去执行,性能肯定是不好的。那么可不可以创建一个 带消息队列的线程,线程不断的从队列中取出任务执行。当队列没有任务时线程处于等待,当我们向队列中放入任务时线程又从队列中取出执行。android向我们提供了HandlerThread,他本质上是一个线程,只不过其内部帮你实现了一个Looper的循环而已。android主线程其实就是HandlerThread,主线程创建时实现了Looper,Looper不断的从消息队列拿消息,我们通过handler发送message到主线程的消息队列,Looper拿到message后调用handler的handleMessage()。
Android开发:带你了解Android的消息机制-通俗易懂
HandlerThread源码分析:
26public class HandlerThread extends Thread {
27 int mPriority;
28 int mTid = -1;
29 Looper mLooper;
30 private @Nullable Handler mHandler;
31
32 public HandlerThread(String name) {
33 super(name);
34 mPriority = Process.THREAD_PRIORITY_DEFAULT;
35 }
36
37 /**
38 * Constructs a HandlerThread.
39 * @param name
40 * @param priority The priority to run the thread at. The value supplied must be from
41 * {@link android.os.Process} and not from java.lang.Thread.
42 */
43 public HandlerThread(String name, int priority) {
44 super(name);
45 mPriority = priority;
46 }
47
从源码可以看到HandlerThread 继承Thread,构造函数中调用父类的构造方法来创建线程。
run()方法解析:
55 @Override
56 public void run() {
57 mTid = Process.myTid();
//创建Looper
58 Looper.prepare();
59 synchronized (this) {
60 mLooper = Looper.myLooper();
//唤醒线程
61 notifyAll();
62 }
//设置优先级
63 Process.setThreadPriority(mPriority);
64 onLooperPrepared();
//Looper开始工作
65 Looper.loop();
66 mTid = -1;
67 }
在run()方法中创建Looper并开始启动looper工作(Looper创建的时候会创建消息队列)
getLooper()方法:
75 public Looper getLooper() {
76 if (!isAlive()) {
77 return null;
78 }
79
80 // If the thread has been started, wait until the looper has been created.
81 synchronized (this) {
82 while (isAlive() && mLooper == null) {
83 try {
84 wait();
85 } catch (InterruptedException e) {
86 }
87 }
88 }
89 return mLooper;
90 }
91
getLooper()获取当前线程的looper对象,如果当前线程未启动直接返回,若启动了但是looper对象未创建线程先挂起。因此在上面run()方法中调用notifyAll()其实就是为了唤醒线程。(就是线程启动了但是looper对象还没创建好,那就先调用wait(),在run()中looper创建好了再唤醒)
HandlerThread的使用:
//创建线程,name是线程名
HandlerThread handlerThread = new HandlerThread("name");
//启动线程
handlerThread.start();
//创建handler,绑定Looper
final Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
//打印线程
System.out.println(Thread.currentThread().getName());
System.out.println(msg.arg1);
}
};
new Thread() {
@Override
public void run() {
Message message = new Message();
message.arg1 = 1;
//在另外的子线程中发送消息
handler.sendMessage(message);
}
}.start();
输出结果:
2019-12-04 15:35:41.559 26537-26618/? I/System.out: name
2019-12-04 15:35:41.560 26537-26618/? I/System.out: 1
1.创建HandlerThread,然后启动。(HandlerThread创建时会创建Looper和消息队列,并且启动Lopper开始工作)
2.getLooper()获取HandlerThread的looper对象
3.创建handler,并且和looper绑定。
4.handler发送消息
5.handler的handleMessage()处理消息
handler发送消息其实就是往HandlerThread线程的消息队列中插入一条消息,looper拿到消息后会调用handler的handleMessage(),而looper又是工作在HandlerThread线程中,所以不难理解handleMessage()为什么会在该线程中工作,使用handler更新UI的时候也是一样,handler绑定的是主线程的looper对象,发送消息后在主线程looper中调用handler的handleMessage(),因此可以在handleMessage()更新UI.
因此HandlerThread结合handler我们就可以实现线程间的通信,当存在多个任务时handler发送多个消息,然后handleMessage()不断的执行任务。而我们只需要创建HandlerThread一个线程就可以搞定,当我们activity退出的时候关闭HandlerThread就可以了。