Java 在这种情况下,我必须同步RPC吗?
昨天我意识到如果我没有同步我的异步请求,我正在做的可能是一个问题——问题是我是否真的必须这样做 让我们来看下面的场景:我有一个顶级视图,它将数据列表Java 在这种情况下,我必须同步RPC吗?,java,gwt,asynchronous,rpc,Java,Gwt,Asynchronous,Rpc,昨天我意识到如果我没有同步我的异步请求,我正在做的可能是一个问题——问题是我是否真的必须这样做 让我们来看下面的场景:我有一个顶级视图,它将数据列表list向下传递到它的子视图。所有下级演示者都将通过添加、删除和修改该列表中的项目来处理该数据列表 假设用户在UI中执行某些操作,然后在多个子级别视图实例上单击“保存”按钮,该按钮将调用subvelPresenter.onSaveSomeObjectButtonClick()。这将执行RPC调用,其结果将添加到列表中 我的假设是,如果用户单击两个不同
list
向下传递到它的子视图。所有下级演示者都将通过添加、删除和修改该列表中的项目来处理该数据列表
假设用户在UI中执行某些操作,然后在多个子级别视图实例上单击“保存”按钮,该按钮将调用subvelPresenter.onSaveSomeObjectButtonClick()
。这将执行RPC调用,其结果将添加到列表中
我的假设是,如果用户单击两个不同的保存按钮,数据可能同时到达,同时触发SaveSomeObjectButtonClick()
,这将导致同时访问列表
我是否必须通过实现一个队列来同步这些操作,例如,或者由于我在这里没有看到的一些内部GWT/JavaScript魔法,我是否安全
public class TopLevelPresenter {
private List<SomeObject> someObjectList = new ArrayList<>();
private List<SubLevelPresenter> cache = new ArrayList<>();
public void TopLevelPresenter(TopLevelModel topLevelModel, TopLevelView topLevelView) {
this.topLevelModel = topLevelModel;
this.topLevelView = topLevelView;
for(int i = 0; i < topLevelModel.getNumOfSubViews(); i++) {
// Pass the data
SubLevelModel subLevelModel = new SubLevelModel(someObjectList);
SubLevelView subLevelView = new SubLevelView();
SubLevelPresenter subLevelPresenter = new SubLevelPresenter(subLevelModel, subLevelView);
cache.add(subLevelPresenter);
}
}
}
public class SubLevelModel() {
private List<SomeObject> someObjectList;
public SubLevelModel(List<SomeObject> someObjectList) {
this.someObjectList = someObjectList;
}
public void addSomeObject(SomeObject someObject) {
this.someObjectList.add(someObject);
}
public void removeSomeObject(SomeObject someObject) {
this.someObjectList.remove(someObject);
}
}
public class SubLevelPresenter() {
private SomeServiceAsync someService = /* .. */;
private SubLevelView subLevelView;
private SubLevelModel subLevelModel;
public SubLevelPresenter(SubLevelModel subLevelModel, SubLevelView subLevelView) {
this.subLevelView = subLevelView;
this.subLevelModel = subLevelModel;
}
public void onSaveSomeObjectButtonClick() {
SomeObject toSave = this.subLevelView.getSuggestionBox().getSelection();
someService.saveSomeObject(toSave, new AsyncCallback<SomeObject>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("RPC to saveSomeObject() failed.");
}
@Override
public void onSuccess(SomeObject savedObject) {
SubLevelPresenter.this.subLevelModel.addSomeObject(savedObject);
}
});
}
}
公共类TopLevelPresenter{
private List someObjectList=new ArrayList();
私有列表缓存=新的ArrayList();
公共void TopLevelPresenter(TopLevelModel TopLevelModel,TopLevelView TopLevelView){
this.topLevelModel=topLevelModel;
this.topLevelView=topLevelView;
对于(int i=0;i
对于您的场景,让多个实例将数据放在RPC之后的列表中似乎是可以的。然而,在这里使用同步列表对同步访问进行排队可能是一个很好的解决方案
Collections.synchronizedList(new ArrayList<String>());
Collections.synchronizedList(新的ArrayList());
鉴于JavaScript是单线程的,因此synchronized
关键字在客户端代码中是无用的(被GWT忽略)。即使RPC响应正好在同一时间到达,它们也会在JavaScript事件循环中排队,并一个接一个地处理
请注意,浏览器中存在导致竞争条件的bug(即),但它们无法像在代码中删除一些synchronized
(或等效)关键字那样容易地被检测和/或解决。另请注意,与alert()
和confirm()
…或CopyOnWriteArrayList
相关。但这只适用于在JVM中运行的代码,而不是在使用GWT编译成JavaScript时,因为JavaScript。好吧,这就是我的想法,但我不确定。那么,假设我真的害怕竞争条件,那么构建一个发送一个又一个请求的队列有意义吗?这似乎只是Firefox的一个变通办法,这将把问题转移到队列管理上。还有一个平衡点:飞行中有2个请求的概率和频率,有缺陷的浏览器中出现竞争情况的概率(注意,我们不知道是否有这样的浏览器,Firefox的问题似乎与阻塞警报()
和确认()
有关,因此取决于您是否使用了其中的任何一个),对代码的影响(包括可维护性)、对性能的影响(以及对用户的感知性能)、如果发生这种情况的后果(“如果用户注意到修复”只需刷新一次)好的,明白了:)谢谢!