例如:
假设有一个按钮启动异步请求,该请求返回并触发主线程上运行的runnable/callback。会发生什么?runnable被添加到MessageQueue中,并在“时间”到时运行。但是什么时候是“时间”呢?如果在异步请求将runnable发布到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]标记的东西表示处理消息
的两种不重叠的方法。如果回调
不为空,则忽略所有[SWITCHED]字段。如果回调
为空,则消息
由[SWITCHED]字段定义,并在处理程序的
重写的handlemessage()
或处理程序的
handlemessage()
中处理。
MessageQueue
按When
字段排序。looper
不会出列并处理消息,直到由SystemClock.uptimeMillis
度量的当前时间大于或等于消息的When
字段中存储的时间。
当调用
处理程序#post(可运行的r)
时,会发生以下情况:
>
从池中获得
消息
(message
类中的简单静态链表)
您的
runnable
被分配给消息的callback
字段。
当
字段简单地设置为当前时间时,如果没有延迟或没有经过特定时间
消息
进入消息队列
。如果when
早于队列头的head,它将成为一个新的head。如果不是,则将其插入中间,以便MessageQueue
保持按When
排序
处理程序决定消息是[可运行的]还是[交换的]并相应地处理它。特别是,如果存在
run()
,则在callback
上调用run()
这将回答您关于阻塞任务期间发布在UI线程上的
runnable
行为的问题--嗯,不,它不会中断正在进行的任务,也不会交织。线程上发生的一切首先进入messagequeue
、按钮单击或您从其他线程发布的自定义runnable
。它基本上不可能以其他方式发生:looper.loop()
只是让线程忙于其for(;;)
循环。
但是,有一些方法可以更改消息的顺序。
此外,您还可以调用一个自解释的
处理程序#postatfrontofqueue()
,正如文档中所指出的那样
这种方法只用于非常特殊的情况--它很容易使消息队列处于饥饿状态,导致排序问题,或者产生其他意想不到的副作用。
我建议您浏览一下所提到的所有类的源代码。它读起来像一本好书。
问题内容: 因此,正如标题所述:将可运行对象从另一个线程发布到主线程时,实际上会发生什么? 我已经看到很多问题,询问您如何执行以及其基本原理。但是,当您将可运行对象放在MessageQueue上时,我很难找到确切的解释。当然,它在轮到Runnable时运行。但是什么时候呢? 因此,例如: 假设有一个按钮启动ASync请求,并且该请求返回并触发在MainThread上运行的可运行/回调。怎么了?可运
在一个android服务中,我创建了用于执行一些后台任务的线程。 我遇到一个情况,线程需要在主线程的消息队列上发布特定任务,例如。 有没有方法获取主线程的并从我的另一个线程向它发布/?
问题内容: 我的一项活动遇到了一个奇怪的问题。从拍照/录像回来时,我正在显示一个对话框,允许用户命名相机。用户按下“确定”后,我将使用所请求的文件名发送给主题,该主题将复制文件(并显示进度对话框)。 由于某种原因,即使我调用,总是在主线程上调用执行复制的函数。 更改呼叫以解决问题。我还是想知道为什么它不起作用… 问题答案: 并且是那里最混乱的运营商。前者确保订阅副作用在指定的调度程序(线程)上发生
我有一个单独的线程在后台运行在C中,我希望它能够发布代码,在另一个已经运行android的线程上运行。操作系统。活套(例如主线)。我所说的“post”是指类似于视图post的东西,其中可运行的排队在事件循环上运行。将要执行的代码也用C编写。 我找到了ALooper API(http://developer.android.com/ndk/reference/group___looper.html)
我如何启动两个线程,其中thread1首先执行,thread2在thread1结束时启动,而主方法线程可以在不锁定其他两个线程的情况下继续工作? 我尝试了join(),但是它需要从线程调用,线程必须等待另一个线程,没有办法执行类似thread2.join(thread1)的操作;因此,如果我在main()中调用join,我将有效地停止主线程的执行,而不仅仅是Thread2的执行。 #编辑:为什么我
我试着运行一个程序,使用线程显示带有数字的乘法、除法、加法和减法表。 但是我希望数字被乘以或相加等。由用户选择。 也就是说,程序应该在用户为每个操作选择一个数字后运行,然后显示结果。