如何使runOnUiThread同步

时间:2019-11-29 20:11:23

标签: java android

此方法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

1 个答案:

答案 0 :(得分:2)

您得到的行为实际上是正确的。因为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);
            }
        }
    });            
}

我认为这足够了。