首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【Android 异步操作】Handler 机制 ( MessageQueue 消息队列的阻塞机制 | Java 层机制 | native 层阻塞机制 | native 层解除阻塞机制 )

wait 方法阻塞 , 直到消息入队时 , 链表中有了元素 , 会调用 notify 解除该阻塞 ; 在实际的 Android 中的 消息队列 MessageQueue 的同步机制 是在 native...层实现 的 ; 在创建 消息队列 MessageQueue 时 , 调用了 nativeInit() 方法 , 销毁 MessageQueue 时调用 nativeDestroy 方法 ; 如果调用...next 获取下一个消息时 , 如果当前消息队列 MessageQueue 中没有消息 , 此时需要阻塞 , 调用 nativePollOnce 即可实现在 native 阻塞线程 ; // 初始化...(ptr, nextPollTimeoutMillis); } } 二、MessageQueue 的 native 层阻塞机制 ---- 线程阻塞方法 private native...---- 在 MessageQueue 消息队列的 Java 层 , 将 Message 消息插入到链表表头后 , 调用了 nativeWake 方法 , 唤醒了线程 , 即解除了阻塞 ; public

1.3K00

深入理解 Android 消息机制原理

最后调用epoll_ctl监控mWakeEventFd文件描述符的Epoll事件,即当mWakeEventFd中有内容可读时,就唤醒当前正在等待的线程.。...什么是Epoll模型呢?我先简单介绍一下。 Epoll(必看!!!) 为什么要引入呢? 在Looper.loop的时候提到了,android不会简单粗暴地真的执行啥都没干的死循环。...Epoll干的事就是: 如果你的queue中没有消息可执行了,好了你可以歇着了,等有消息的我再告诉你。这个queue.next就是“阻塞”(休眠)在这里。...其实native层主要负责的是消息的调度,比如说何时阻塞、何时唤醒线程,避免CPU浪费。...native发送 发送在native比较简单,handler发送消息后,会到MessageQueue的enqueueMessage,此时在线程阻塞的情况下,会调用nativeWake来唤起线程。

2K41
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    Android中的Handler机制中的问题总结

    获取,来保证每个线程间只会有一个Looper对象 当有Message要进入Looper时,从ThreadLocal中获取Looper Loop的实现原理 Looper通过Linux的epoll来实现阻塞唤醒的...// 那么就会唤醒执行任务, 不直接执行任务的原因是这个函数可能会在子线程被调用 msg.next = p;..., MessageQueue.next()会走到以下逻辑开始处理Idlehandler // 当消息链表中没有需要处理的消息时 if (pendingIdleHandlerCount...例如, 当前主线程中有A->B->C->D->E五个消息, 而当E需要高优执行的时候(其实就是Android中的VSync重绘任务), 其中A为SyncBarrier, 则当轮到A执行的时候, MessageQueue...当需要插入任务时, 使用Handler.getLooper().getMessageQueue().postSyncBarrier()插入栅栏, 在要插入的消息中设置Message.setAsynchronous

    1.1K20

    看完这篇,别再说你不了解 Handler 消息机制了

    的逻辑会根据 Message 的执行时间 Message.when 按大小排序,队头 when 小,队尾 when 大,然后判断线程是否休眠,如果是,则调用 native 方法 nativeWake 唤醒线程...Runnable B、消息进队,判断现在 A 时间还没到、正在阻塞,把 B 插入消息队列的头部(A的前面),然后调用nativeWake()方法唤醒线程;MessageQueue.next()方法被唤醒后...所以这也是为什么在主线程中可以直接实例化 Handler 的原因。...当前线程会阻塞在 loop() 里面的 mQueue.next() 方法中,MessageQueue 的 next() 方法中也有一个死循环,没有更多消息的时候,会阻塞在这个循环里面。...这里不是简单的死循环,所以阻塞不会消耗太大的资源,无消息的时候线程会进入休眠状态,CPU 资源会被释放给其他线程使用;当有新消息的时候,线程会被唤醒,继续执行 loopMessage next() {

    73421

    Looper,MassageQuene,Handler

    所以一个线程一个Looper一个MessageQuene多个Handler 主线程和子线程使用区别 主线程为什么不用进行Looper.prepare()和Looper.loop()方法的调用就可以使用Hnadler...而其他子线程需要调用上述两个方法才能使用Handler。...所以主线程也要调用只不过ActivityThread帮你做了 大概流程 Looper中for(;;)死循环调用MessageQuene的next()方法(该方法也为for(;;)死循环)取出最新消息。...MessageQuene中取消息时会判断target是否为空(同步屏障消息),如果为空去取下一个消息:如果为同步消息不发送,异步消息才进行发送 主线程如何在for(;;)情况实现不阻塞主线程 MessageQuene...中没有消息会调用nativePollOnce进行阻塞用于标识当前无消息,当有消息进入队列时会调用nativeWake进行唤醒队列。

    41020

    「细品源码」 Android 系统的血液:Handler

    如何判断这个位置呢?依然是通过消息被执行的时间。 通过遍历整个队列,当队列中的某个消息的执行时间比当前消息晚时,将消息插到这个消息的前面。...最后是一个空闲监听处理,作用是当队列中没有需要执行的消息时,说明线程进入空闲状态,这时候可以去执行一些其他的任务。...唤醒线程 当消息队列为空的时候,Loop 会进入无限阻塞挂起,如果这时候用户发送了一个消息,这时候如何唤醒线程呢?...当 timeoutMillis == 0 或者超时唤醒时,会跳转到 Done ,结束调用,返回。...Loop.looper() 死循环为什么不会阻塞主线程 经过上面的分析,App 的主线程中通过 Loop.looper() 开启了消息“死循环”,那为什么 App 依然可以正常运转,没有阻塞到主线程呢

    1K60

    Handler:Android 消息机制,我有必要再讲一次!

    子线程为啥一定要调用 Looper.prepare() 和 Looper.loop()? Handler 的简单使用 相信应该没有人不会使用 Handler 吧?...这是一个 Native 方法,实际作用是通过 Native 层的 MessageQueue 阻塞当前调用栈线程 nextPollTimeoutMillis 毫秒的时间。...置为 -1,此时满足小于 0 的条件,会被一直阻塞,直到其他地方调用另外一个 Native 方法 nativeWake(long) 进行唤醒。...ThreadLocal 是用来存储指定线程的数据的,当某些数据的作用域是该指定线程并且该数据需要贯穿该线程的所有执行过程时就可以使用 ThreadnLocal 存储数据,当某线程使用 ThreadnLocal...可能你会疑问,我在主线程使用的时候,没有要求 Looper.prepare() 呀。

    39210

    深入解析Android中Handler消息机制

    Handler的简单使用 为什么系统不允许子线程更新UI 因为的UI控件不是线程安全的。 如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那为什么不对UI控件的访问加上上锁机制呢?...通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象...Looper的,但是为什么在主线程没有创建的Looper就可以使用Handler?...主线程,也就是ActivityThread,当主线程被创建的时候,会调用Looper内的prepareMainLooper方法,创建Looper,该方法是专门给主线程创建Looper用的。...当MessageQueue没有消息时,next方法会一直阻塞在那里,因为MessageQueue的next方法阻塞了,就导致Looper的loop方法也一直在阻塞了。

    53230

    深入理解Android消息机制

    为什么主线程不卡? 分析完基本的消息机制,既然 Looper 的 looper 方法是一个for(;;;)循环,那么新的问题提出来了。为什么Android会在主线程使用死循环?...执行死循环的时候为什么主线程的阻塞没有导致CPU占用的暴增?...继续分析在源码中我们没有分析的部分: 消息队列构造的时候是否调用了jni部分 nativeWake、nativePollOnce这些方法的作用是什么 先查看MQ的构造方法: MessageQueue(boolean...的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知 关于epoll和select,可以举一个例子来表达意思。...Java层通过调用 pollonce 来达到调用底层epoll 让死循环进入阻塞休眠的状态,以避免浪费CPU, 所以这也解释了为什么Android Looper的死循环为什么不会让主线程CPU占用率飙升

    53820

    面试官还问Handler?那我要给你讲个故事

    如果消息为异步消息则通过Message.when长短插入到队列对应位置,不唤醒Looper线程。 接下来该面试官问了 经常有人问为什么主线程的Looper阻塞不会导致ANR?...首先我们得知道ANR是主线程5秒内没有响应。 什么叫5秒没有响应呢?Android系统中所有的操作均通过Handler添加事件到事件队列,Looper循环去队列去取事件进行执行。...那子线程怎么创建Handler呢?只需在new Handler()之前调用下Looper.prepare()即可。 2. 为什么主线程可以直接new Handler?...子线程直接new Handler会报错,主线程为什么就不会报错呢?主线程我也没有调用Looper.prepare()啊?那么我们还得看下源码了。...垃圾回收机制:Java采用根搜索算法,当GC Roots不可达时,并且对象finalize没有自救的情况下,才会回收。

    44360

    Android面试必备知识点:Android中Handler八大问题汇总

    首先给出结论,Looper不会一直消耗系统资源,当Looper的MessageQueue中没有消息时,或者定时消息没到执行时间时,当前持有Looper的线程就会进入阻塞状态。...再看看下面这个方法:nativePollOnce(ptr, nextPollTimeoutMillis);当nextPollingTimeOutMillis=-1时,这个native方法会阻塞当前线程,...线程阻塞后,等下次有消息入队才会重新进入可运行状态,所以Looper并不会一直死循环消耗运行内存,对队列中的颜色消息还没到时间时也会阻塞当前线程,但是会有一个阻塞时间也就是nextPollingTimeOutMillis...当消息队列中没有消息的时候looper肯定是被消息入队唤醒的。...; } 上面可以看到消息入队之后会有一个 if (needWake) { nativeWake(mPtr); } 方法,调用这个方法就可以唤醒线程了

    1.2K20

    Android Handler机制 – MessageQueue如何处理消息

    而next方法显然就是用于获取下一条消息的,其中主要通过nativePollOnce从native层的MessageQueue中获取,并且该方法会阻塞线程,如果获取不到消息(比如消息队列中是空的),就一直阻塞...本次调查的结论 nativePollOnce 确实没有导致ANR,也不会过度消耗cpu cycle,它只是说明当前handlerthread中没有需要处理的message,线程在等待下一条message...,当其值为 false 时,不会crash,只是 listFiles() 接口返回的那个有问题的文件名不一定能准确识别出来,我想Google做这种机制的目的在于,开发时通过crash提示开发者有非utf...利用epoll的机制,可以做到当管道没有消息时,线程睡眠在读端的fd上,当其他线程往管道写数据时,本线程便会被唤醒以进行消息处理。...loop方法里会调用MessageQueue的next方法。next方法会堵塞线程直到有消息到来为止。 next方法通过调用nativePollOnce方法来监听事件。

    72920

    面试问关于Handler的这些问题你知道吗?

    Looper.loop() 为什么不会阻塞APP? 可以监测到 MessageQueue 中无数据的情况吗?可以的话,通过什么方式?...---- Handler 相关问题的解答 以下代码中省略了无关代码 Q :在线程中可以直接调用 Handler 无参的构造方法吗?在主线程和子线程中有没有区别?...A:因为在没有可用消息的时候会休眠,然后 当 MessageQueue 有可用消息之后(新增的 when时)会通过 epoll机制 唤醒。...当 Message 得不到处理时,被 Handler 持有的外部对象会一直处于内存泄漏状态。 ---- Q :在子线程中如何获取当前线程的 Looper?...A:调用静态方式 Looper.myLooper(),在子线程中没有调用 Looper.prepare()时,返回null. public static @Nullable Looper myLooper

    28260

    Android 一起来看看面试必问的消息机制

    Handler 的主要功能是将任务切换到某个指定的线程中去执行,那么 Android 为什么要提供这个功能呢?...这是因为 Android 规定访问 UI 只能在主线程中进行,如果在子线程中访问 UI,那么程序就会抛出异常。 那为什么 Android 不允许子线程中访问 UI 呢?...这是因为 Android 的 UI 控件并不是线程安全的,如果在多线程中并发访问可能会导致 UI 控件处于不可预期的状态,那还有一个问题,为什么系统不对 UI 控件的访问加上锁机制呢?...我们知道,Handler 的工作需要 Looper,没有 Looper 的线程就会报错,那么如何为一个线程创建 Looper 呢?...的 quit() 被调用时,Looper 就会调用 MessageQueue 的 quit() 或者 quitSafely() 方法来通知消息队列退出,当前消息队列被标记为退出状态时,它的 next

    33730

    深入Handler、Looper、MessageQueue

    调用nativePollOnce(ptr, nextPollTimeoutMillis)进行阻塞,这是一个本地方法,会调用底层C++代码,C++代码最终会通过Linux的epoll监听文件描述符的写入事件来实现延迟...二、Looper.loop是一个死循环,拿不到需要处理的Message就会阻塞,那在UI线程中为什么不会导致ANR?...ActivityThread没有继承Thread,他不是主线程。个人猜测当前进程就是主线程。 1.为什么要阻塞 一个线程,如果执行完成,该线程会消亡。...如果当前Looper不阻塞,执行完成,那app直接嗝屁。 2.阻塞后为什么还能跳转页面等操作 这个问题是2个问题。第一个是如何执行页面跳转等操作,第二个是阻塞后为什么还能操作页面。...第二个,阻塞后还能操作,跳转页面,还能调用各种声明周期。我们可以看到ActivityThread定义了内部类Handler,他和Looper都是在同一线程即主线程。

    37120

    Android 进阶14:源码解读 Android 消息机制( Message MessageQueue Handler Looper)

    如果有阻塞(没有消息了或者只有 Delay 的消息),会把 mBlocked这个变量标记为 true,在下一个 Message 进队时会判断这个message 的位置,如果在队首就会调用 nativeWake...public static interface IdleHandler { //当消息队列没有消息时会回调这个方法,阻塞等待有消息进入 //返回 true 的话表示唤醒阻塞的线程,false...表示移除 //如果消息队列中有消息等待在将来执行,也会调用这个方法 boolean queueIdle(); } 根据源码和注释我们可以知道 IdleHandler 是一个线程阻塞时回调的接口...mLogging; private long mTraceTag; 线程中默认没有 Looper,我们需要调用 Looper.prepare() 方法为当前线程创建一个 Looper,然后就可以调用 loop...这时消息已经在创建 Handler 的线程了 这个“线程切换” 是怎么实现的呢?

    1.4K90

    【面试专题】2021年字节、阿里、网易等 Handler 面试题集合,Android高级开发必备!

    Looper死循环为什么不会导致应用卡死?...Handler是native层的阻塞、唤醒(nativePollOnce、nativeWake)机制,应用卡死那是ANR(这边可以展开说一下 ANR),有条件的可以说一下 Linux 底层的消息机制(这个绝对是加分项...这边可能会被问,sThreadLocal为什么是static的?这边答案我不太确定,我面试的时候是答的只需要装载一次,减少对象创建开销;线程内所有操作共享。有知道为什么的大佬可以评论区教教大家。...,可能会了立即返回(立即执行); 等于-1时,无消息时,会一直堵塞; 阻塞内部就是通过native函数nativePollOnce、nativeWake来实现的,这边可以展开说,说清楚了你就是P7大佬了...当线程将要进入堵塞,以等待更多消息时,会回 调这个接口。简单点说:当MessageQueue中无可处理的Message时回调。

    1.8K21
    领券