Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使runOnUiThread同步_Java_Android - Fatal编程技术网

Java 如何使runOnUiThread同步

Java 如何使runOnUiThread同步,java,android,Java,Android,此方法onRemoteVideoStateChanged被异步调用,并且previous\u uid是一个全局变量,设置为0 @Override public void onRemoteVideoStateChanged(final int uid, int state, int reason, int elapsed) { super.onRemoteVideoStateChanged(uid, state, reason, elapsed); runOnUiTh

此方法
onRemoteVideoStateChanged
被异步调用,并且
previous\u 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;
                }
            }
        }
    });            
}
我希望使用唯一的uid只调用一次方法
setUpRemoteVideo

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

2019-11-30 01:24:56.667我的日志:以前的uid=0 uid=656786280

2019-11-30 01:24:56.673我的日志:以前的uid=0 uid=656786280


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

您可以创建一个
static synchronized
函数,该函数将根据
previous\u uid
返回真/假,因此通过使函数线程安全,您可以控制
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;
        }
    }
}
现在,在执行
setupRemoteVideo
操作之前,可以先从
onRemoteVideoStateChanged
检查
uid

@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);
            }
        }
    });            
}

我认为这应该足够了

在我看来,您正在
Runnable
实例上进行同步。由于您总是创建新的
Runnable
s,这种同步对您没有多大好处。除了初始化之外,
previous\u uid
是否可以在您发布的代码之外的任何地方访问?如果没有,那么@Michael提到的问题就放在一边,“同步”块的目的是什么?
previous\u uid
不在其他地方访问。同步块的目的是防止对同一uid多次调用方法调用
setupRemoteVideo
@scgYes,你是对的@Michael,但是你能提供一个同步的解决方案吗?你能检查我的答案并让我知道这是否有效吗?