Android SDK 中的事件循环已经是一个老生常谈的问题了, 像 Handler Looper MessageQueue 这几个类也是被大家研究透彻了.
但是再回头看以前自己的分析, 总感觉差点什么, 不够透彻. 心里隐隐感觉自己没有把事情完全吃透, 于是今日又回顾 Android 中的事件循环机制, 注意到
MessageQueue 中获取下一条消息时会执行一个 native 调用 nativePollOnce, 翻看 Android 系统源码发现有内容.

来自高手的解释

首先, 先梭哈一把 stackoverflow 上高手对这个问题(android - what is message queue native poll once in android?)的回答原文:

Short answer:

The nativePollOnce method is used to "wait" till the next Message becomes available. If the time spent during this call is long, your main (UI) thread has no real work to do and waits for next events to process. There's no need to worry about that.

Explanation:

Because the "main" thread is responsible for drawing UI and handling various events, it's Runnable has a loop which processes all these events. The loop is managed by a Looper and its job is quite straightforward: it processes all Messages in the MessageQueue.

A Message is added to the queue for example in response to input events, as frame rendering callback or even your own Handler.post calls. Sometimes the main thread has no work to do (that is, no messages in the queue), which may happen e.g. just after finishing rendering single frame (the thread has just drawn one frame and is ready for the next one, just waits for a proper time). Two Java methods in the MessageQueue class are interesting to us: Message next() and boolean enqueueMessage(Message, long). Message next(), as its name suggest, takes and returns the next Message from the queue. If the queue is empty (and there's nothing to return), the method calls native void nativePollOnce(long, int) which blocks until a new message is added. At this point you might ask how does nativePollOnce know when to wake up. That's a very good question. When a Message is added to the queue, the framework calls the enqueueMessage method, which not only inserts the message into the queue, but also calls native static void nativeWake(long), if there's need to wake up the queue. The core magic of nativePollOnce and nativeWake happens in the native (actually, C++) code. Native MessageQueue utilizes a Linux system call named epoll, which allows to monitor a file descriptor for IO events. nativePollOnce calls epoll_wait on a certain file descriptor, whereas nativeWake writes to the descriptor, which is one of the IO operations, epoll_wait waits for. The kernel then takes out the epoll-waiting thread from the waiting state and the thread proceeds with handling the new message. If you're familiar with Java's Object.wait() and Object.notify() methods, you can imagine that nativePollOnce is a rough equivalent for Object.wait() and nativeWake for Object.notify(), except they're implemented completely differently: nativePollOnce uses epoll and Object.wait() uses futex Linux call. It's worth noticing that neither nativePollOnce nor Object.wait() waste CPU cycles, as when a thread enters either method, it becomes disabled for thread scheduling purposes (quoting the javadoc for the Object class). However, some profilers may mistakenly recognize epoll-waiting (or even Object-waiting) threads as running and consuming CPU time, which is incorrect. If those methods actually wasted CPU cycles, all idle apps would use 100% of the CPU, heating and slowing down the device.

Conclusion:

You shouldn't worry about nativePollOnce. It just indicates that processing of all Messages has been finished and the thread waits for the next one. Well, that simply means you don't give too much work to your main thread ;)


translate.google 一下

Android 中 MessageQueue 的 nativePollOnce的更多相关文章

  1. Android中线程间通信原理分析:Looper,MessageQueue,Handler

    自问自答的两个问题 在我们去讨论Handler,Looper,MessageQueue的关系之前,我们需要先问两个问题: 1.这一套东西搞出来是为了解决什么问题呢? 2.如果让我们来解决这个问题该怎么 ...

  2. Android中的Handler及它所引出的Looper、MessageQueue、Message

    0.引入 0.1.线程间通信的目的 首先,线程间通信要交流些什么呢? 解答这个问题要从为什么要有多线程开始,需要多线程的原因大概有这些 最早也最基本:有的任务需要大量的时间,但其实并不占用计算资源,比 ...

  3. 深入源代码解析Android中的Handler,Message,MessageQueue,Looper

    本文主要是对Handler和消息循环的实现原理进行源代码分析.假设不熟悉Handler能够參见博文< Android中Handler的使用>,里面对Android为何以引入Handler机 ...

  4. Android笔记(三十三) Android中线程之间的通信(五)Thread、Handle、Looper和MessageQueue

    ThreadLocal 往下看之前,需要了解一下Java的ThreadLocal类,可参考博文: 解密ThreadLocal Looper.Handler和MessageQueue 我们分析一下之前的 ...

  5. 重温Android中的消息机制

    引入: 提到Android中的消息机制,大家应该都不陌生,我们在开发中不可避免的要和它打交道.从我们开发的角度来看,Handler是Android消息机制的上层接口.我们在平时的开发中只需要和Hand ...

  6. Android中为什么主线程不会因为Looper.loop()方法造成阻塞

    很多人都对Handler的机制有所了解,如果不是很熟悉的可以看看我 如果看过源码的人都知道,在处理消息的时候使用了Looper.loop()方法,并且在该方法中进入了一个死循环,同时Looper.lo ...

  7. Android中对消息机制(Handler)的再次解读

    今天遇到一些关于在子线程中操作Handler的问题,感觉又要研究源代码了,但是关于Handler的话,我之前研究过,可以参考这篇文章:http://blog.csdn.net/jiangwei0910 ...

  8. Android中后台的劳动者“服务”

    前言 作为四大组件之一的Service,想必不少开发者都是了解的,那具体熟悉吗?是不是对Service中的每个知识点是否了解,它与Activity的关系又是什么样的,我们所理解的后台服务跟Servic ...

  9. Android中使用Handler造成内存泄露的分析和解决

    什么是内存泄露?Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用所指向 ...

随机推荐

  1. day 32 操作系统、线程和进程(GIL锁)

    一.操作系统/应用程序 a. 硬件 - 硬盘 - CPU - 主板 - 显卡 - 内存 - 电源 ... b. 装系统(软件) - 系统就是一个由程序员写出来软件,该软件用于控制计算机的硬件,让他们之 ...

  2. 2019年12月2日Linux开发手记

    开始学习在Linux下视频源捕获驱动框架,也就是V4L2(video4linux),本次关于v4l2的知识准备主要在于其的官方例程,理解官方例程也就差不多掌握了v4l2的基本内容.例程在:http:/ ...

  3. 基于 HTML5 + WebGL 的太阳系 3D 展示系统

    前言 近年来随着引力波的发现.黑洞照片的拍摄.火星上存在水的证据发现等科学上的突破,以及文学影视作品中诸如<三体>.<流浪地球>.<星际穿越>等的传播普及,宇宙空间 ...

  4. 【数据结构】之二叉树(Java语言描述)

    有关树的一些基础知识点请参考[这篇文章]. 本文主要记录Java语言描述的二叉树相关的一些操作,如创建.遍历等. 首先,我们需要一个表示树中节点的数据结构TreeNode,代码如下: public c ...

  5. 【Android - 自定义View】之View的draw过程解析

    draw(绘制)过程的作用是将View绘制到屏幕上面.View中有 draw() 方法和 onDraw() 方法,但onDraw()方法是空方法:ViewGroup中没有draw()方法,也没有onD ...

  6. Django4模型(操作数据库)

    模型入门同步数据库的两个指令创建模型注意事项1.外键ForeignKey 模型入门 同步数据库的两个指令 python manage.py makemigrations python manage.p ...

  7. C语言I作业10

    问题 回答 这个作业属于哪个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/SE2019-2/homework/10100 我在 ...

  8. python中的局部变量和全局变量

  9. 拿 C# 搞函数式编程 - 2

    前一阵子在写 CPU,导致一直没有什么时间去做其他的事情,现在好不容易做完闲下来了,我又可以水文章了哈哈哈哈哈.顺便成立了自己的专栏:hez2010 的编程日常,欢迎大家关注(逃 有关 FP 的类型部 ...

  10. Calling the Web Service dynamically (.NET 动态访问Web Service)

    针对.NET平台下的WebService访问,为达到不添加引用的情况下,动态调用外部服务. 主体方法: public class WebServiceHelper { //Calling the We ...