转载请标明出处:http://www.jianshu.com/users/13aada6bd6a3/latest_articles
CSDN地址:http://blog.csdn.net/liuhe_5656/article/details/52416542
概述
在日常开发中,我们经常会通过new Thread(){}.start();的方式来开辟一个新的线程。但是如果我们想要多次执行任务的时候,通过这种方式我就会创建多个线程,这样会使我们的程序运行起来越来越慢。通常情况下我会采用HandlerThread的方式来开辟一个线程,那么HandlerThread是什么呢?今天我们来介绍一下HandlerThread。
正文
HandlerThread是Thread的一个子类,HandlerThread自带Looper使他可以通过消息队列来重复使用当前线程,节省系统资源开销。这是它的优点也是缺点,每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。它的使用也比较简单
HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
mHandler = new Handler(thread.getLooper());
mHandler.post(new Runnable(){...});
接下来我们写一个完整的Demo,然后在分析一下它的实现原理。
Demo代码
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的源码
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的时候可以通过qiut()的方法来终止。
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()来终止它的循环。
尾语
今天的总结就到这了,如果大家发现不足请留言告知,一定及时修改。