你担心handlerThread的效率问题吗?
属性之间的关联
handlerThread、handler、looper、messageQueue相互关联对应
queue
Queue是通过msg.next指向下一个msg来实现,mMessages代表当前的message,每取出一个msg,移动一次mMessages,一直到最后一个msg
handlerThread
handlerThread是一个线程,做的事情就是让looper循环在messageQueue中找下一个message(上图中的mMessages一直往后移动)
在移动的过程中:
1. 如果有message,就在handler中执行message中的callback或者runnable.run(),然后继续找下一个message
2. 如果message=null(handlerThread调用quit()方法后,会在查找msg的过程中直接返回null),则跳出循环,handlerThread就执行完了,
并不是没找到msg就返回null:
在next()的过程中,如果没有找到message,还会进行一次循环
而在这次循环中,nextPollTimeoutMills=-1,mBlocked=true,nativePollOnce()会把线程中断下来,此时不会返回msg,而是被中断下来了。
来消息的时候,(由于之前mblocked=true,所以)会nativeWake()唤醒线程,
不过都是在这两个native方法都是MessageQueue中进行的
以此达到节省资源的目的
注意
由于代码中有native方法,初看的时候会认为handlerThread一直在循环取queue中的msg, (这样说来,该线程一直在占有时间片,而又没处理实际的任务,效率实在地下)(该理解是错误的)
再看的时候会发现,如果没有取到msg,该handlerThread的run方法就会走完,也就是说,thread走完之后会停止 (这样说来,一旦queue中的msg被取完,handlerThread就停止了,那,再次sendMessage的时候,又如何会执行?)(该理解是错误的)
直到调试发现,在没有msg的时候会进行中断,来了msg的时候又会唤醒。
于是效率并不成问题
那么,该handlerThread什么时候会结束呢,
前面说过:handlerThread有个quite方法,该方法会改变一个标记位,这个标记位被改变后,queue循环查找下一个msg的时候会直接返回null,looper循环处理msg的时候发现msg=null,然后会跳出循环,而handlerThread的存活就是靠run()方法中 looper的死循环的,一旦循环跳出,那么说run方法就会直接走完,到此线程结束。
欢迎关注我的微信公众号:云端看大地
即将带来的是:我工作经验系列文章(包括安卓开发,以及编程经验,还有工作中的方方面面需要注意的地方)
正准备的是:预测**的系列文章
敬请期待