removeCallbacksAndMessages是否序列化?

时间:2017-05-20 21:23:48

标签: android handler

出于示例的目的,假设我有两个异步调用的方法,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语句之前首先执行或根本不执行。

1 个答案:

答案 0 :(得分:1)

  

removeCallbacksAndMessages是否强制进行序列化,即在移除或执行runnable之前阻止执行?

如果在主应用程序线程上执行doEventB()(或者更准确地说,在Handler绑定到的同一线程上),则应该处于正常状态。 Handler为此使用了MessageQueueMessageQueue确实同步删除了邮件,至少在Android 7.1中。

然而:

  • 这是未记录的行为AFAIK,因此存在其他版本的Android表现不同的风险

  • 如果你在另一个线程上调用doEventB(),虽然应该没有线程同步问题(例如ConcurrentModificationException),你可能会遇到竞争条件:doEventB()是在一个线程上调用,Runnable开始在另一个线程上执行,doEventB()日志消息发生在Runnable日志消息之前