Looper.loop()会不会阻塞主线程

Looper.loop()会阻塞主线程吗

答案是肯定的,主线程的loop会阻塞主线程,不过这并不是问题,那么原因是什么呢?

ActivityThread 是App的入口,这里可以看到 main 方法,它是整个java程序的入口。ActivitvThread 的 main 方法主要作用是消息循环,一旦消息循环停止,那么程序也就可以退出了。
我们必须明白,Android是事件驱动的,在Loop.loop0中不断接收、处理事件,才能保证Android的生命周期执行下去,而Activity的生命周期都由主线程的Loop.loop0来调度。

很显然当目前没有事件需要处理的时候,主线程就会阻塞,当子线程向消息队列发送消息,主线程就被唤醒。

主线程的loope如果没有消息,那么loop里面就会被 messageQueue 阻塞。因为Android系统是事件驱动的,所以我们写的代码就是通过handler驱动起来的,我们activity的生命周期方法,包括我们的UI绘制的信号,这些UI绘制的事件都是通过Handler Looper循环内部发起的。

这些所有的事务都被封装成为了一个一个的message,然后通过loper来调用handleMessage回调到主线程,所以我们的代码就是在循环里面执行的,也就是主线程一切皆Message。

ActivityThread 的 main 方法主要作用就是做消息循环,一旦退出消息循环,那么程序也就可以退出了。
从消息队列中取消息可能会引起阻塞,取到消息会做出相应的处理。如果某个消息执行时间过长,就可能会影响 UI 线程的刷新效率,造成卡顿的现象

死循环问题

Looper.loor()方法中会调用死循环去从MessageQueue中读取message

public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
      
       //死循环,其中loopOnce中调用了messageQueue.next()方法读取消息
        for (;;) {
            if (!loopOnce(me, ident, thresholdOverride)) {
                return;
            }
        }
    }


 private static boolean loopOnce(final Looper me,
            final long ident, final int thresholdOverride) {

            Message msg = me.mQueue.next(); // might block可能阻塞的

}
            

如上代码loop.looper()死循环调用MessageQueue.next()读取消息

死循环会不会导致我们的CPU在我们没消息的时候在那里空转呢?实际上如果你没有什么事情可做,那么MessageQueue里面有一个nativePollOnce的这个方法,这个方法是个native方法,本地方法调用这个方法其实就是调用Linux里面的一个管道机制epoll。没有消息的时候,调用epoll wait,它就会等待在那里,实际上调用完wait之后,就会释放我们的CPU,就等于我们的应用在休眠状态,它不会让CPU一直在那里空转。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容