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,但是你能提供一个同步的解决方案吗?你能检查我的答案并让我知道这是否有效吗?