概述
在日常开发中,我们经常会通过 new Thread(){}.start();
的方式来开辟一个新的线程。但是如果我们想要多次执行任务的时候,通过这种方式我就会创建多个线程,这样会使我们的程序运行起来越来越慢。通常情况下我会采用 HandlerThread 的方式来开辟一个线程,那么 HandlerThread 是什么呢?今天我们来介绍一下 HandlerThread。
正文
HandlerThread 是 Thread 的一个子类,HandlerThread 自带 Looper 使他可以通过消息队列来重复使用当前线程,节省系统资源开销。这是它的优点也是缺点,每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。它的使用也比较简单。
1
2
3
4
5
6
7
| HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
mHandler = new Handler(thread.getLooper());
mHandler.post(new Runnable(){
//...
});
|
接下来我们写一个完整的 Demo,然后在分析一下它的实现原理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| public class MainActivity extends AppCompatActivity {
private HandlerThread handlerThread;
private Handler handler;
private Button button;
private int k = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
handlerThread = new HandlerThread("suibian");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.post(runnable);
}
});
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++){
try {
Thread.sleep(1000);
Log.d("test","第" + k + "个任务--》" + i + "");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
k++;
}
};
@Override
protected void onDestroy() {
super.onDestroy();
handlerThread.quit();
}
}
|
我们连续点击两次 Button,让它执行两次任务,我们来看一下它的 Log 信息。
我们发现它不会立即去执行第二次任务,而是等待第一次任务结束之后再去执行第二次任务,我们来看一下它的原理。
源码分析
我们来看一下 HandlerThread 的源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
...
/**
* Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
*/
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;
}
.....
}
|
它的代码比较短,我们主要来看一下它的 run() 方法,我们发现它和普通 Thread 不同之处在于它在 run() 方法内创建了一个消息队列(如果不太了解消息机制的同学可以看一下 Android 中的消息机制来了解一下),然后来通过 Handler 的消息的方式来通知 HandlerThread 执行下一个具体的任务。由于 HandlerThread 的 run() 方法内 Looper 是个无限循环,所以当我们不需要使用 HandlerThread 的时候可以通过 quit() 的方法来终止。
1
2
3
4
5
6
7
8
| public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
|
quit() 实际上就是让 run() 内的 Looper 停止循环。
整体流程
当我们使用 HandlerThread 创建一个线程,它 statr() 之后会在它的线程创建一个 Looper 对象且初始化了一个 MessageQueue(消息队列),通过 Looper 对象在他的线程构建一个 Handler 对象,然后我们通过 Handler 发送消息的形式将任务发送到 MessageQueue 中,因为 Looper 是顺序处理消息的,所以当有多个任务存在时就会顺序的排队执行。当我们不使用的时候我们应该调用它的 quit() 或者 quitSafely() 来终止它的循环。
本文转载自:https://www.jianshu.com/p/5b6c71a7e8d7