如何阻止现有的异步Web请求?

时间:2015-03-26 15:25:17

标签: java rx-java

我已经向第三方库提供了回调,该库在不同时间调用提供的方法,为我提供了一个已更改的对象。然后我执行异步Web请求以获取更多详细信息并将其设置在该对象上,下面是一个类似的示例;

public void update(Person person) {
     if (person.getId() == -1) {
         mService.getPersonDetails()
                 .flatMap(..)
                 .skip(..)
                 .subscribe(personResult -> person.setId(personResult.getId()))
     }
}

更新被调用了很多次,并且只应在对象没有ID时才执行查询。问题是,当第一个查询尚未完成时,至少会发送两个请求。

如何同步此方法调用,以便只为通过回调传递的每个Object发送一个请求?我只想阻止对该确切Object的请求,因此如果update()提供不同的对象,则可以发送新的请求。

3 个答案:

答案 0 :(得分:3)

Adam S提供的解决方案看起来不错,但很快或以后都会导致OOM问题。这是由于不同的运营商必须存储所有唯一值。

我想到的另一个选择是使用ConcurrentMap来存储已处理的人员,并使用doOnTerminate来清理它。

    private Map<Person, Boolean> map = new ConcurrentHashMap<>();
    public void update(final Person person) {
     if (person.getId() == -1) {
        if(map.putIfAbsent(person, true)==null){
           mService.getPersonDetails()
                 .flatMap(..)
                 .skip(..)
                 .doOnTerminate(()->map.remove(person))
                 .subscribe(personResult -> person.setId(personResult.getId()))
        }
     }
}

答案 1 :(得分:1)

您可以使用distinct运算符过滤您的observable的输入。以下是关于如何使用PublishSubjectJavaDoc)来做到这一点的一般概念(注意这是从记忆中写的,我还没有对此进行过测试):

private PublishSubject<Person> personSubject;
public void update(Person person) {
     if (personSubject == null) {
         personSubject = new PublishSubject();
         personSubject
            .filter(person -> person.getId() == -1)
            .distinct()
            .flatMap(person -> mService.getPersonDetails())
            .skip(..)
            .subscribe(personResult -> person.setId(personResult.getId()));
     }
     personSubject.onNext(person);
}

当然,您必须在equals类上实现Person方法(正如Marek指出的那样,将导致所有传入的对象被缓存在内存中)或实现distinct(Func)变体。

该方法需要一个键选择器&#39;用于区分对象的函数。如果你的对象相当沉重并且你关注内存(例如,如果你在Android上),这可能是一条更好的道路。像这样:

.distinct(new Func1<Person, Integer>() {
                @Override
                public Integer call(Person person) {
                    return person.hashCode();
                }
            })

答案 2 :(得分:-1)

嗯,你可以简单地synchronize

public synchronized void update(Person person)