出于示例的目的,假设我有两个异步调用的方法,doDelayEventA和doEventB。为简化起见,我们假设doDelayEventA将被调用一次,而doEventB将被调用一次。
doDelayEventA启动一个计时器(实际上是一个处理程序)并且doEventB将其杀死(如果它仍处于挂起状态)。
private Handler mTimer;
public void doDelayEventA(){
mTimer = new Handler();
mTimer.postDelayed(new Runnable() {
public void run() {
Log.d(LOG_TAG, "Event A: We want this to happen FIRST or not at all");
}
}, 1000);
}
public void doEventB(){
if (mTimer != null) {
mTimer.removeCallbacksAndMessages(null);
}
Log.d(LOG_TAG, "Event B: If it happens, it should ALWAYS happen LAST");
}
问题:removeCallbacksAndMessages是否强制进行序列化,即在移除或执行runnable之前阻止执行?我想确保在调用这两种方法的情况下,EventA Log语句将始终在EventB Log语句之前首先执行或根本不执行。
答案 0 :(得分:1)
removeCallbacksAndMessages是否强制进行序列化,即在移除或执行runnable之前阻止执行?
如果在主应用程序线程上执行doEventB()
(或者更准确地说,在Handler
绑定到的同一线程上),则应该处于正常状态。 Handler
为此使用了MessageQueue
,MessageQueue
确实同步删除了邮件,至少在Android 7.1中。
然而:
这是未记录的行为AFAIK,因此存在其他版本的Android表现不同的风险
如果你在另一个线程上调用doEventB()
,虽然应该没有线程同步问题(例如ConcurrentModificationException
),你可能会遇到竞争条件:doEventB()
是在一个线程上调用,Runnable
开始在另一个线程上执行,doEventB()
日志消息发生在Runnable
日志消息之前