此方法onRemoteVideoStateChanged被异步调用,并且previous_uid是全局变量,并设置为0。

@Override
public void onRemoteVideoStateChanged(final int uid, int state, int reason, int elapsed) {
    super.onRemoteVideoStateChanged(uid, state, reason, elapsed);

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            synchronized (this)
            {
                if (previous_uid != uid) {
                    Log.d("TAG", "previous_uid = " + previous_uid + "  uid = "+ uid );
                    setupRemoteVideo(uid);
                    previous_uid = uid;
                }
            }
        }
    });
}


我希望方法setUpRemoteVideo仅应使用唯一的uid调用一次。

但出乎意料的是,它被多次调用了,这是日志:


  2019-11-30 01:24:56.667 D / MY_LOGS:previous_uid = 0 uid = 656786280
  
  2019-11-30 01:24:56.673 D / MY_LOGS:previous_uid = 0 uid = 656786280

最佳答案

您得到的行为实际上是正确的。因为onRemoteVideoStateChanged调用是异步的,并且可能出现从两个后台异步线程同时调用此函数的情况,所以这解释了您发布的日志。这里的关键思想是if(previous_uid != uid)不是线程安全的。

您可以创建一个static synchronized函数,该函数将基于previous_uid返回true / false,因此通过使该函数成为线程安全函数,可以控制setupRemoteVideo函数仅针对唯一的uid进行调用。让我尝试给你一个例子。

public class UIDProvider {
    private static int uid = 0;

    public static synchronized boolean isDifferentThanStoredUid(int uid) {
        if (this.uid != uid) {
            this.uid = uid; // assign the new value here
            return true;
        } else {
            return false;
        }
    }
}


现在,可以从onRemoteVideoStateChanged首先检查uid,然后再执行setupRemoteVideo操作。

@Override
public void onRemoteVideoStateChanged(final int uid, int state, int reason, int elapsed) {
    super.onRemoteVideoStateChanged(uid, state, reason, elapsed);

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            // The check actually does not provide uniqueness. It justs check with the previous uid as far as I could understand. If you want uniqueness, then you might have to store all the values previously seen in a HashMap and look for the uid in the HashMap.
            if (UIDProvider.isDifferentThanStoredUid(uid)) {
                Log.d("TAG", "previous_uid = " + previous_uid + "  uid = "+ uid );
                setupRemoteVideo(uid);
            }
        }
    });
}


我认为这足够了。

关于java - 如何使runOnUiThread同步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59110503/

10-10 03:36