android - 什么是消息队列原生轮询在 android 中?

2022-09-01 02:30:39

我知道线程有一个消息队列,处理程序能够将runnables或消息推送到它们,但是当我使用Android Studio工具分析我的Android应用程序时,有一个奇怪的过程:

android.os.MessageQueue.nativePollOnce

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

enter image description here


答案 1

简短的回答:

该方法用于“等待”,直到下一个可用。如果此调用期间花费的时间很长,则主 (UI) 线程没有实际工作要做,而是等待下一个事件处理。无需担心。nativePollOnceMessage

解释:

因为“主”线程负责绘制UI和处理各种事件,所以它有一个循环来处理所有这些事件。循环由循环器管理,其工作非常简单:它处理消息队列中的所有消息Runnable

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

结论:

您不必担心 .它只是表示所有消息的处理都已完成,线程正在等待下一个消息。好吧,这仅仅意味着你不会给你的主线程太多的工作;)nativePollOnce


答案 2

推荐