2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > android HandlerThread源码解析

android HandlerThread源码解析

时间:2021-11-07 01:42:40

相关推荐

android HandlerThread源码解析

尊重原创,转载请注明出处:/a740169405/article/details/50257001

HandlerThread概述

HandlerThread是一个线程类。HandlerThread内部创建了一个消息队列,其他线程可以通过Handler向其发送消息。HandlerThread按照消息的发送顺序依次对消息进行处理。HandlerThread在所有消息执行完毕后,线程并不会自动退出,消息队列任然在等待新任务。

一、HandlerThread内部消息队列的初始化

在线程成功执行后,HandlerThread创建了一个消息队列,用来接收其他线程发来的消息:

@Overridepublic void run() {mTid = Process.myTid();// 为当前线程创建LooperLooper.prepare();synchronized (this) {// 获取当前线程Looper对象mLooper = Looper.myLooper();// 唤醒其他等待线程notifyAll();}Process.setThreadPriority(mPriority);// mLooper对象初始化完成后回调onLooperPrepared();// 开始循环读取消息队列里的消息Looper.loop();mTid = -1;}

该方法调用了Looper.prepare();创建了一个消息队列。这样,该线程就能接收handler发送的消息了。

最后调用了Looper.loop();开始循环读取消息。

二、向HandlerThread发送消息

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 创建线程,命名为"myHandlerThread"HandlerThread handlerThread = new HandlerThread("myHandlerThread");// 启动线程handlerThread.start();// 创建Handler,并指定使用HandlerThread的消息队列来处理消息MyHandler myHandler = new MyHandler(handlerThread.getLooper());// 发送一条空消息给消息队列myHandler.obtainMessage().sendToTarget();}public static class MyHandler extends Handler {public MyHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);// 收到消息后,打印出当前线程的名字Log.e(TAG, "current Thread name : " + Thread.currentThread().getName());}}

我在主线程中初始化了一个HandlerThread线程,并启动了该线程。

向HandlerThread的消息队列发送了一条消息,消息收到后输出了当前线程的名字。

.myapplication E/HandlerThreadActivity: current Thread name : myHandlerThread

后台输出的名字正是我创建线程的时候传递进去的。

通过上面的例子我们发现,向handlerThread发送的消息,是由HandlerThread线程来处理的。

三、HandlerThread锁机制:

大家注意这一段代码:

synchronized (this) {mLooper = Looper.myLooper();notifyAll();}

加锁是为了确保其他现成获取该线程的Looper时不为空。

我们再看看HandlerThread提供的获取Looper的方法:

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;}

代码的意思很简单,如果Looper还未创建,则进入等待状态,直到Looper被创建。

我尝试写一个HandlerThread的子类来验证一下:

public static class MyHandlerThread extends HandlerThread {public MyHandlerThread(String name) {super(name);}@Overridepublic void run() {try {// 在线程启动后,初始化消息队列之前,sleep三秒Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}// 调用父类的run方法初始化消息队列super.run();}@Overridepublic Looper getLooper() {return super.getLooper();}}

逻辑很简单,重写run方法,在调用父类run方法进行Looper初始化之前让线程sleep三秒。

添加一些Log:

MyHandlerThread handlerThread = new MyHandlerThread("myHandlerThread");// 线程启动前,先打个log记录当前时间SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Log.e(TAG, "current time = " + formatter.format(new Date()));handlerThread.start();Looper looper = handlerThread.getLooper();// 在getLooper();之后打印log记录当前时间Log.e(TAG, "get looper success, send message, time = " + formatter.format(new Date()));MyHandler myHandler = new MyHandler(looper);// 发送消息myHandler.obtainMessage().sendToTarget();

再看看log:

E/HandlerThreadActivity: current time = -12-11 08:45:03

E/HandlerThreadActivity: get looper success, send message, time = -12-11 08:45:06

E/HandlerThreadActivity: current Thread name : myHandlerThread

从log中可以看出主线程等待了三秒,之所以加锁是为了防止在looper未被初始化之前,其他线程调用getLooper方法得到空对象。

注意:

一般我们是不需要重写HandlerThread类,只需要使用Handler对象向HandlerThread的消息队列发送消息,在handleMessage函数里处理消息,就可以了,且处理消息的线程是HandlerThread这个线程。

上面的例子中,我在消息队列初始化之前sleep了3秒,导致了主线程在getLooper的时候等待了3秒,也就是说有可能造成主线程ANR。

四、HandlerThread的退出

需要注意的是,一旦执行Looper.loop();线程便进入循环获取消息状态,也就是说线程不会自己停止,我们可以一直往线程发送消息,如果需要停止线程,只要调用HandlerThread对象的quit();或者quitSafely();函数,这两个函数其实只是调用了Looper对象的quit();或者quitSafely();函数:

HandlerThread的quit();函数:

public boolean quit() {// 获取当前线程的LooperLooper looper = getLooper();if (looper != null) {// 立即停止Looper的循环,不在处理未处理完的消息looper.quit();return true;}return false;}

HandlerThread的quitSafely();函数:

public boolean quitSafely() {// 获取当前线程的LooperLooper looper = getLooper();if (looper != null) {// 打上需要停止循环的标志,等到消息都处理完以后,再推出循环looper.quitSafely();return true;}return false;}

这两者的区别在于,调用quit();会直接终止消息队列的循环,如果队列中还有其他消息未处理,将不会被处理。

而调用quitSafely();函数则是给消息队列打上退出循环的标记,在所有消息处理完成以后,Looper自动退出循环,从而线程也就会结束。

总结:

1. HandlerThread类是google提供的一个,在线程内创建消息循环队列的线程API,让除了主线程以外的子线程也具有消息处理能力。2. 使用时记得先调用HandlerThread的run方法启动线程3. 在创建Handler时使用HandlerThread的Looper对象。4. 确认所有任务都处理完成以后,记得调用HandlerThread推出函数,建议使用quitSafely();这样会等到所有消息都处理完后再推出线程。

应用:

HandlerThread在IntentService中应用到。

关于IntentService的项管内容,大家可以阅读我的另一片博客:Android IntentService的使用与源码解析

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。