美文网首页线程 安卓面试宝典Android开发
【Android面试】主线程中的Looper.loop()一直无

【Android面试】主线程中的Looper.loop()一直无

作者: itbird01 | 来源:发表于2017-03-13 10:30 被阅读768次

    Android面试中,你也许会被问到题目中的问题,这里我们基于以下几点来延伸解读其中原因:

    1、什么是ANR?ANR发生的原因是什么?

    2、Looper为什么要无限循环?

    3、线程的几种状态

    4、主线程中的Looper.loop()一直无限循环为什么不会造成ANR?

    1、什么是ANR?ANR发生的原因是什么?

    ANR即Application Not Responding,顾名思义就是应用程序无响应。

    在Android中,一般情况下,四大组件均是工作在主线程中的,Android中的Activity Manager和Window Manager会随时监控应用程序的响应情况,如果因为一些耗时操作(网络请求或者IO操作)造成主线程阻塞一定时间(例如造成5s内不能响应用户事件或者BroadcastReceiver的onReceive方法执行时间超过10s),那么系统就会显示ANR对话框提示用户对应的应用处于无响应状态。

    简单总结就是以下两点:

    1. 不要让主线程干耗时的工作

    2. 不要让其他线程阻塞主线程的执行

    2、Looper为什么要无限循环?

    Looper中重要的两个方法为prepare()、loop()

    prepare()源码

    Looper在prepare中通过ThreadLocal保证了每个线程Looper对象的唯一性,即对于每个线程,有唯一的Looper对象和MessageQueue队列

    loop()源码

    显而易见的,主线程中如果没有looper进行循环,那么主线程一运行完毕就会退出。那么我们还能运行APP吗,显然,这是不可能的,Looper主要就是做消息循环,然后由Handler进行消息分发处理,一旦退出消息循环,那么你的应用也就退出了。

    总结:Looper的无限循环必不可少

    3、线程的几种状态

    很多读者会问,你说的好好地Looper,干嘛突然转到线程状态的知识点了呢?

    别急别急,请允许老衲细细道来。

    众所周知,线程的五大状态为:New、Runnable、Running、Blocked、Dead,而他们之间有者千丝万缕的关系,为了便于大家理解,看图说话

    线程状态图

    很多人会问,为什么有这么多Blocked?

    (1)新建状态(New):新创建了一个线程对象。

    (2)就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

    (3)运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

    (4)阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

    等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。

    同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

    其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

    不管线程进入哪种阻塞状态,都得等所等待的事件(wait、sleep、join、synchronized、I/O)完成后,才可以进入就绪队列,排队等待CPU资源

    (5)死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

    4、主线程中的Looper.loop()一直无限循环为什么不会造成ANR?

    也许讲到这里,很多人已经知道原因了吧!不过习惯使然,我还是要总结一下。

    主线程Looper从消息队列读取消息,当读完所有消息时,主线程阻塞。子线程往消息队列发送消息,并且往管道文件写数据,主线程即被唤醒,从管道文件读取数据,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。因此loop的循环并不会对CPU性能有过多的消耗

    讲到这里,各位看官应该知道为什么上面要引入线程状态的了解了吧。

    相关文章

      网友评论

        本文标题:【Android面试】主线程中的Looper.loop()一直无

        本文链接:https://www.haomeiwen.com/subject/nckfnttx.html