安卓 - 什么是安卓中的消息队列本地轮询一次?

49

我知道线程有一个消息队列,处理程序能够将可运行项或消息推送到它们,但是当我使用Android Studio工具对我的Android应用程序进行分析时,出现了一个奇怪的进程:

android.os.MessageQueue.nativePollOnce

它比其他进程更多地使用了CPU。它是什么,我如何减少CPU花费在它上面的时间?您可以在下面找到分析器结果。

enter image description here


1
看起来像是忙等待。答案不是使用轮询。您没有发布任何代码或有关应用程序的其他信息。 - chrylis -cautiouslyoptimistic-
1
什么是忙等待? - Sajad Norouzi
1个回答

83

简短回答:

nativePollOnce 方法用于“等待”,直到下一个 Message 可用。如果此调用期间花费的时间很长,您的主(UI)线程没有真正的工作要做,会等待下一个事件进行处理。不需要担心这个问题。

解释:

由于“主”线程负责绘制 UI 并处理各种事件,因此它的 Runnable 具有处理所有这些事件的循环。 该循环由 Looper 管理,其工作非常简单:处理 MessageQueue 中的所有消息。

例如,响应输入事件、帧渲染回调甚至您自己的Handler.post调用,都可能向队列添加Message。有时主线程没有工作要做(也就是说,队列中没有消息),这可能发生在完成渲染单个帧之后(线程刚刚绘制了一个帧并准备好下一个帧,只是等待适当的时间)。MessageQueue类中的两个Java方法对我们很有趣:Message next()boolean enqueueMessage(Message, long)Message next()顾名思义,从队列中获取并返回下一个消息。如果队列为空(没有任何内容可以返回),该方法会调用native void nativePollOnce(long, int),它将阻塞直到添加新消息。此时,您可能会问nativePollOnce如何知道何时唤醒。那是一个非常好的问题。当向队列添加Message时,框架调用enqueueMessage方法,该方法不仅将消息插入队列,而且还会在需要唤醒队列时调用native static void nativeWake(long)nativePollOncenativeWake的核心魔法发生在本地(实际上是C ++)代码中。原生的MessageQueue利用了一个名为epoll的Linux系统调用,它允许监视IO事件的文件描述符。 nativePollOnce在某个文件描述符上调用epoll_wait,而nativeWake写入该描述符之一,这是IO操作之一,epoll_wait等待。然后内核将等待状态的epoll线程取出,并继续处理新消息。如果您熟悉Java的Object.wait()Object.notify()方法,则可以想象nativePollOnceObject.wait()的粗略等效项,nativeWakeObject.notify()的粗略等效项,但它们的实现完全不同:nativePollOnce使用epoll,而Object.wait()使用futex Linux调用。值得注意的是,nativePollOnceObject.wait()都不会浪费CPU周期,因为当线程进入任一方法时,它会因线程调度目的而被禁用(引用Object类的javadoc)。但是,某些分析器可能错误地将epoll等待(甚至是Object等待)线程识别为正在运行并消耗CPU时间,这是不正确的。如果这些方法实际上浪费了CPU周期,则所有空闲应用程序都将使用100%的CPU,从而加热和减慢设备。

结论:

你不必担心nativePollOnce。它只是表示所有消息的处理已经完成,线程等待下一个消息。这意味着你不应该给你的主线程过多的工作;)


1
如果队列中没有消息,nativePollOnce 如何知道等待多久或者何时唤醒? - Florian Walther
2
@Florian,我刚刚更新了我的答案以提供更多细节(并纠正了原始答案中的一些错误信息)。 - Lawiusz
2
@linjiejun 主线程执行渲染任务的指令可能来自框架(例如输入事件等)或应用程序本身(例如当您安排动画时等)。请参阅Choreographer类描述以获取更多信息(https://developer.android.com/reference/android/view/Choreographer)。 - Lawiusz
10
为什么我的应用程序会在nativePollOnce处收到ANR错误提示? - Marian Paździoch
2
@MarianPaździoch 这是错误的,真正的ANR原因不是nativePollOnce。 - twlkyao
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接