所以,正如标题所说:当您将另一个线程的可运行文件发布到主线程时,实际上会发生什么?
我看到很多问题询问你是如何做到的,以及它的基本原理是如何工作的。但是,当您在 MessageQueue 上放置一个 runnable 时,我很难找到一个确切的解释。轮到 Runnable 时它会运行,当然。但这是什么时候?
例如:
假设有一个按钮启动异步请求,并且请求返回并触发在 MainThread 上运行的可运行/回调。怎么了? runnable 被添加到 MessageQueue 并在“时间”时运行。但是什么时候是“时间”?如果我在异步请求将可运行对象发布到 MainThread 之前按下另一个按钮,该按钮在 MainThread 上执行一些半长阻塞任务怎么办?它会等到我的阻止按钮上的逻辑完成吗?它会打断它吗?它是否将可运行代码与我的阻塞代码按钮的代码交织在一起?究竟会发生什么?
我问的主要原因是这样我可以更好地了解我需要牢记哪些注意事项以防止由于多线程导致的错误。 (特别是旧请求影响已刷新页面的情况)
最佳答案
首先,你需要了解Message
是什么上课就像。一个 Message
对象包含以下其他字段:
Handler target; // a handler that enqueued the message
long when; // the time at which the message is to be processed
[RUNNABLE] Runnable callback; =
[SWITCHED] int what, int arg1, int arg2, Bundle data...
bool isAsynchronous; // I will talk about it in the end
我用 [RUNNABLE] 和 [SWITCHED] 标记的内容代表处理
Message
的两种非重叠方式。 .如果 callback
不为空,所有 [SWITCHED] 字段都将被忽略。如果 callback
比 Message
为空由 [SWITCHED] 字段定义并在 Handler's
中处理。覆盖 handleMessage()
或 handleMessage()
的Handler.Callback
处理程序被初始化。MessageQueue
按 when
排序 field 。 Looper
直到当前时间(由 SystemClock.uptimeMillis
测量)才会出列并处理消息, 大于或等于消息的 when
中存储的时间 field 。当您调用
Handler#post(Runnable r)
发生以下事情:Message
从池中获取(一个简单的静态链表在
Message
类)Runnable
分配给消息的 callback
field 。 when
如果没有延迟或特定,则字段仅设置为当前时间时间已过
Message
排入MessageQueue
.如果 when
是早于队列的头部,它成为一个新的头部。如果
不是,而是插入到中间,以便
MessageQueue
仍按 when
排序Looper
这是一个非终止循环,使消息出队从队列中按顺序处理它们(无交织),
最终,将我们的消息出列并调用
dispatchMessage()
上最初发布
Runnable
的处理程序. [SWITCHED] 并相应地处理它。特别是它调用
run()
在 callback
如果存在 这应该可以回答您关于
Runnable
行为的问题。在阻塞任务期间发布在 UI 线程上 - 嗯,不,它不会中断正在进行的任务,也不会交织 .线程上发生的所有事情首先进入MessageQueue
。 , 按钮点击或您的自定义 Runnables
您从其他线程发布的。基本上不可能以其他方式发生:Looper.loop()
只是让线程忙于它的for(;;)
环形。不过,有一些方法可以更改消息的顺序。
例如,在 Looper/Handler 框架中有一个有趣的同步屏障概念。按照惯例,同步屏障只是
Message
为空 target
(所以它基本上只是一个类似标志的东西,没有处理程序来调度它)。如果它与 postSyncBarrier()
一起放入队列中,出列的整个过程发生变化,直到同步屏障从队列中移除 removeSyncBarrier()
. Messages
未标记为 isAsynchronous
将被忽略,根本不会出队和处理。相反,将扫描队列,直到出现 isAsynchronous = true
的消息。被发现。然后将根据其when
进行调度。并在时机成熟时进行处理。此外,您可以调用不言自明的
Handler#postAtFrontOfQueue()
, 但是,正如文档中指出的那样This method is only for use in very special circumstances -- it can easily starve the message queue, cause ordering problems, or have other unexpected side-effects.
建议您浏览source code所有提到的类。它读起来就像一本很好的小说书。
关于java - Android:将另一个线程的可运行文件发布到主线程实际上有什么作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34124845/