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

时间:2016-08-07 21:16:19

标签: java android performance cpu profile

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

  

android.os.MessageQueue.nativePollOnce

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

enter image description here

1 个答案:

答案 0 :(得分: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()方法,则可以设想nativePollOnceObject.wait()nativeWake相当于Object.notify()除了它们的实现完全不同之外:nativePollOnce使用epollObject.wait()使用futex Linux调用。值得注意的是,nativePollOnceObject.wait()都没有浪费CPU周期,因为当线程进入任一方法时,它会因线程调度而被禁用(引用Object类的javadoc)。但是,某些分析器可能会错误地将epoll等待(甚至是对象等待)线程识别为正在运行并消耗CPU时间,这是不正确的。如果这些方法实际上浪费了CPU周期,那么所有空闲应用程序都将使用100%的CPU,加热并降低设备速度。

<强>结论:

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