简短的回答:
该方法用于“等待”,直到下一个可用。如果此调用期间花费的时间很长,则主 (UI) 线程没有实际工作要做,而是等待下一个事件处理。无需担心。nativePollOnce
Message
解释:
因为“主”线程负责绘制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.post
MessageQueue
Message next()
boolean enqueueMessage(Message, long)
Message next()
native void nativePollOnce(long, int)
nativePollOnce
Message
enqueueMessage
native static void nativeWake(long)
nativePollOnce
nativeWake
nativePollOnce
epoll_wait
nativeWake
epoll_wait
Object.wait()
Object.notify()
nativePollOnce
Object.wait()
nativeWake
Object.notify()
nativePollOnce
epoll
Object.wait()
nativePollOnce
Object.wait()
Object
结论:
您不必担心 .它只是表示所有消息的处理都已完成,线程正在等待下一个消息。好吧,这仅仅意味着你不会给你的主线程太多的工作;)nativePollOnce
-
为什么在此方法中添加 If 语句会大大降低它的速度? 我在 之间切换。 有趣的行为是,当我决定哪一个更快并删除如果代码的速度放大10倍时。之前需要140毫秒,之后只有13毫秒。我应该只从循环中删除大约7个计算中的一个。为什么速度会如此急
-
jProfiler如何处理JIT? 我广泛使用jProfiler,它是一个很棒的工具,但我想知道jProfiler如何处理JIT编译的影响。 例如,我是否能够观察到方法内联?如果一个方法是内联的,那么它在快照中根本不可见,或者jProfiler仍
-
为什么此代码使用锁运行得更快? 一些背景:我创建了一个人为的示例,向我的团队演示 VisualVM 的使用。特别是,一个方法有一个不必要的关键字,我们看到线程池中的线程阻塞,它们不需要。但是删除该关键字具有下面描述的
-
无断言编译 我知道可以在运行时分别启用/禁用断言以进行调试和生产。但是,我发现断言也会增加生成的二进制文件的大小(在下面的示例中约为100-200字节)。 在 C 和 C++ 中,我们可以在编译时通过 before
-
我有一个我不理解的Java性能问题 我写了一些代码来制作一个多维数组,而不是一个数组数组,这样我就可以节省一些内存。然后我运行了一些测试,将其速度与常规Java数组数组(int[][])的速度进行比较,因为我不希望我的程