博客
关于我
主线程中Looper的轮询死循环为何没有阻塞主线程?
阅读量:578 次
发布时间:2019-03-11

本文共 1262 字,大约阅读时间需要 4 分钟。

在Android系统中,主线程执行耗时操作会导致ANR(Application Not Responding)异常,这是一个开发者常需要关注的问题。ANR异常通常有两种原因:一是当前事件没有机会处理,比如主线程被阻塞,无法及时处理事件;二是正在处理的事件没有及时完成。这可能导致用户体验中的卡顿或应用崩溃。

为了避免这种问题,Android开发者通常会使用Handler消息处理机制,通过子线程执行耗时操作。然而,这一设计原理背后的逻辑并不直观,具体来说,主线程中的Looper.loop()无限循环检测消息队列有无新消息,会不会导致ANR异常?

当我们仔细看一下Looper.loop()的实现方式:它在一个死循环中不断地从消息队列中取出消息进行处理。如果主线程不退出这个循环,那么应用程序就不会退出。这是因为Android的 ActivityThread 类通过它的 main 方法执行Looper.loop(),只要这个循环继续进行,主线程就不会退出。而只有当所有消息都处理完毕后,Looper.loop()才会退出,但这种情况下通常不会发生,因为我们必须确保主线程有足够的处理能力来处理所有的事件。

那么,主线程为什么不会因为主线程的消息处理而陷入死锁呢?因为主线程的Looper-loop()只是在处理消息,它从消息队列中读取消息,实际处理消息的任务是在消息的分发端。那什么时候会发生ANR异常呢?实际上,导致ANR的原因并不是主线程被阻塞,而是主线程在处理事件的时候处理得过慢。只要主线程的消息处理速度快于事件的产生速度,就不会出现ANR。

在主线程的消息处理中,每个消息的处理时间只要不要过长,应用程序就不会出现卡顿。当用户触发某个操作时,子线程通过Handler发送消息到主线程的消息队列中,这样就不会阻塞主线程。主线程只需要轮询消息队列中的消息,而不是一直等待。因此,Looper-loop()本身不会引起主线程被阻塞,只有因为消息处理过慢才会导致ANR异常。

此外,Looper-loop()内部的实现机制也做了一些优化。消息队列会自动处理多余的消息,避免主线程被过多的消息占塞。此外,Android系统还会根据进程的优先级管理消息处理,这可以进一步保证主线程的响应能力。

所以可以说,主线程的Looper-loop()一直保持活跃状态,只是处理消息而已,自身并不阻塞。当主线程处理某个消息时,即使它占用了一定的时间,它只是在该消息处理完毕后继续处理下一个消息,而不会卡住整个主线程。这也是Android不容易出现ANR异常的重要原因。

总的来说,主线程之所以不会因为Looper-loop()而阻塞,是因为它不断地处理消息,而不是被消息所阻塞。只有当主线程在处理某个具体的消息时过于缓慢,才能导致用户感知到的卡顿或ANR异常。因此,在开发Android应用时,我们需要特别注意耗时操作的执行位置,避免在主线程中进行耗时操作,将耗时操作移至子线程,这样既保证了应用程序的响应性,又避免了ANR异常的发生。

转载地址:http://wwttz.baihongyu.com/

你可能感兴趣的文章
Chrome查找发请求的js之黑箱调试
查看>>
CMCC登录参数分析
查看>>
GridView的另外一种分页方式,可提高加载速度
查看>>
GridView自定义删除操作
查看>>
一张图搞定RPC框架核心原理
查看>>
Scala中的包
查看>>
参加阿里的Java面试经验
查看>>
Python微信公众号
查看>>
他来了他来了,他带着云栖大会的免费门票走来了
查看>>
获取linux 主机cpu类型
查看>>
限流的算法有哪些?
查看>>
Android Studio updating indices 一直刷新和闪烁
查看>>
个人购买服务器问题?
查看>>
pwntools编写技巧
查看>>
How2Heap笔记(三)
查看>>
go--microSocket服务端 php客户端
查看>>
小程序提交新数据后如何返回上一页并刷新数据?
查看>>
qt c++实现的ai贪吃蛇吃满屏幕,超详细!(二)ai的具体实现
查看>>
linux 查看log日志相关命令
查看>>
IDEA 2019 安装 mybatis-plus插件
查看>>