请问安卓中Looper.loop()不是一个死循环吗?它是怎么让出CPU的?

作者:超级管理员 更新时间:2017-10-27 10:59:19 来源:未知 点击:15642
问题1:如标题  我能想到的是 Thread.wait() ??也不对 这样主线程就不会往下执行了  问题2:请问为什么不直接把LOOPER作为handler的成员变量而是要把他与线程绑定呢?----
问题1:如标题  我能想到的是 Thread.wait() ??也不对 这样主线程就不会往下执行了  
问题2:请问为什么不直接把LOOPER作为handler的成员变量而是要把他与线程绑定呢?
-------------------------------
-------------------------------
@经常在黑云中出没   
-------------------------------
Looper.loop();中的for语句源码: 
for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
          。。。。。(一系列操作)
    }

当queue消息队列中没有消息时候会退出循环
-------------------------------
@经常在黑云中出没   

引用 3 楼 qq_15530467 的回复:
Looper.loop();中的for语句源码: 
for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
          。。。。。(一系列操作)
    }

当queue消息队列中没有消息时候会退出循环
当有消息的时候它是怎么又回到这段代码里的啊?
-------------------------------
引用 4 楼 u012280292 的回复:
@经常在黑云中出没   

Quote: 引用 3 楼 qq_15530467 的回复:

Looper.loop();中的for语句源码: 
for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
          。。。。。(一系列操作)
    }

当queue消息队列中没有消息时候会退出循环
当有消息的时候它是怎么又回到这段代码里的啊?


有消息的时候,系统会触发这个方法
-------------------------------
http://blog.csdn.net/ashqal/article/details/32107099
看下这个,讲的很清楚
-------------------------------
引用 3 楼 qq_15530467 的回复:
Looper.loop();中的for语句源码: 
for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
          。。。。。(一系列操作)
    }

当queue消息队列中没有消息时候会退出循环


我觉得不是这样,
Message msg = queue.next(); // might block

后面的注释说明了在queue的next()中可能阻塞,再看MessageQueue的next()实现
Message next() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }

                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }

                // If first time idle, then get the number of idlers to run.
                // Idle handles only run if the queue is empty or if the first message
                // in the queue (possibly a barrier) is due to be handled in the future.
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            // Run the idle handlers.
            // We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;

            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }

第17行的nativePollOnce(ptr, nextPollTimeoutMillis)是native方法,它在内部调用了epoll_wait(),这个方法实现流程大概是有message就返回,没有的话就一直等待并且监听管道的事件;当Java层有新的message(或者barrier)被添加至messageQueue时,会触发native方法nativeWake,这个方法的里面大概是往管道中写入一个“w”,这样就会唤醒epoll_wait,继而使nativePollOnce方法返回,继续执行17行以后的部分。

推荐阅读

热门内容

android中textview蚊子多显

如图所示,文本字数多了的话最后显示省略号...

【请教大神】webview如何引入swf

我在/res/raw中放入了一个.swf...

模拟器上可以显示我解析的json数据,但

本帖最后由ds1995于2016-05-...

如何层次显示图片缩略图?

如何像下图这样的层次感显示3个缩略图?没...

Android 在 Eclipse 中关

求大佬帮帮忙,很烦这个问题-------...

打开AndroidStudio出现Sta

昨天还可以打开,今天早上打开就出现这个报...

求助!!!关于二级评论的数据错位问题

之前看了通过Android Listvi...

安卓开发一些新手问题

第一个问题为什么会报错?第二个问题为什么...

tablayout的tab能将图标放大点

本帖最后由qq_37587427于201...

请问一下状态栏怎么实现渐变

如图所示,TOOLBAR实现了渐变(通过...

最新内容

jquery使用iscorll实现上拉、下拉加载刷新

本文实例为大家分享了iscorll实现上拉下拉加载刷新的具体代码,供大家参考,具...

AngularJs用户登录问题处理(交互及验证、阻止FQ处理)

本文介绍了AngularJs用户登录的交互及验证、阻止FQ处理,具体如下1.静态...

node文字生成图片的示例代码

今天老板提了需求,要在服务端生成邀请卡,嗯…,简单的说就是把要这张:变成差多这样...

vue-cli中打包图片路径错误的解决方法

最近第一次使用vue-cli构建项目,第一次打包部署到服务器上的时候出现图片加载...

javascript+html5+css3自定义弹出窗口效果

本文实例为大家分享了js自定义弹出窗口效果展示的具体代码,供大家参考,具体内容如...

Vue 兄弟组件通信的方法(不使用Vuex)

项目中,我们经常会遇到兄弟组件通信的情况。在大型项目中我们可以通过引入vuex轻...

在 Laravel 中 “规范” 的开发短信验证码发送功能

Laravel简介Laravel是一套简洁、优雅的PHPWeb开发框架(PHPW...

JS手机端touch事件计算滑动距离的方法示例

本文实例讲述了JS手机端touch事件计算滑动距离的方法。分享给大家供大家参考,...

详解php 使用Callable Closure强制指定回调类型

详解php使用CallableClosure强制指定回调类型如果一个方法需要接受...

JavaScript实现二叉树的先序、中序及后序遍历方法详解

本文实例讲述了JavaScript实现二叉树的先序、中序及后序遍历方法。分享给大...

php静态成员方法和静态的成员属性的使用方法

php静态成员方法和静态的成员属性的使用方法静态成员方法和静态的成员属性如下使用...

JavaScript实现树的遍历算法示例【广度优先与深度优先】

本文实例讲述了JavaScript实现树的遍历算法。分享给大家供大家参考,具体如...

PHP中类型转换 ,常量,系统常量,魔术常量的详解

PHP中类型转换,常量,系统常量,魔术常量的详解1.自动类型转换;在运算和判断时...

利用php获得flv视频长度的实例代码

废话不多说了,直接给大家贴代码了,具体代码如下所示:functionBigEnd...

详述 Sublime Text 打开 GBK 格式中文乱码的解决方法

SublimeText是一个代码编辑器,其具有漂亮的用户界面和强大的功能,例如代...

PHP 中魔术常量的实例详解

PHP中魔术常量的实例详解本文介绍下,php编程中的魔术常量,掌握并灵活应用这些...

node.js的exports、module.exports与ES6的export、export default深入详解

前言最近难得有空,决定开始重新规范的学习一下node编程。但是引入模块我看到用r...

yii框架redis结合php实现秒杀效果(实例代码)

废话不多说了,直接给大家贴代码了,具体代码如下所示:

PHP对象的浅复制与深复制的实例详解

PHP对象的浅复制与深复制的实例详解最近在看原型模式时注意到这个问题~~PHP中...

PHP中的浅复制与深复制的实例详解

PHP中的浅复制与深复制的实例详解前言:最近温习了一下DesignPattern...