removeCallbacksAndMessages 是否序列化?

Does removeCallbacksAndMessages serialize?

举例来说,假设我有两个异步调用的方法,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 语句执行或根本不执行。

Does the removeCallbacksAndMessages force a serialization, that is, does it block execution until the runnable has been removed or executed?

如果 doEventB() 在主应用程序线程上执行(或者,更准确地说,在与 Handler 绑定的同一线程上),您应该处于正常状态。 Handler 为此使用 MessageQueue,并且 MessageQueue 确实同步删除消息,至少在 Android 7.1.

但是:

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

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

  • 之前