android - 什么是android中的消息队列本机轮询?

问题描述 投票:18回答:1

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

android.os.MessageQueue.nativePollOnce

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

enter image description here

java android performance cpu profile
1个回答
26
投票

简短回答:

nativePollOnce方法用于“等待”直到下一个Message变得可用。如果在此调用期间花费的时间很长,则您的主(UI)线程无需执行任何实际工作,并等待下一个要处理的事件。没有必要担心这一点。

说明:

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

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

结论:

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

© www.soinside.com 2019 - 2024. All rights reserved.